purpose of notebook

(/) describe & visualize relationship between variables (multivariate) (/) gather interesting observations for further investigation (x) gather possible new features for extraction

todos: (-) …

information

name: makeovermonday_2021w22 link: https://data.world/makeovermonday/2021w22 title: 2021/W22: The Plastic Waste Makers Index Data Source: Minderoo from 2019

insights

(!) are there two different sub-populations in the data? like two different types of producers with different behavior regarding rigid_format and flexible_format production -> may be there are producers with only rigid format -> if group is identified, then add a variable to tag them and make the plots again with group coloring, I wonder if there are also the producers with total_waste_div_production ration 1.0

  1. no_of_assets over rank increases only slowly until rank 25, afterwards it starts to increase strongly (compared to before), this is where the outliers come in from no_of_assets distribution, but most assets in not rank 1
  2. production_of_in_scope_polymers over rank starts to increase again substantially after about rank 25
  3. flexible_format_contribution_to_sup_waste over rank starts to increase again substantially after about rank 25, there are a couple of producers above rank 25 which do not produce flexible_format (like outliers), the spread is very high towards the end
  4. rigid_format_contribution_to_sup_waste over rank starts to increase again substantially after about rank 25, but compared to flexible_format the spread is not as high (except for one outlier, which is also really low on flexible format), but overall there is less production in rigid_format
  5. total_contribution_to_sup_waste over rank, seems to be oddly stepped, but that is because the rank is directly determined by the total_contribution (there are not independent), again the steep increase starts at rank 25
  6. low no_of_assets seems to also imply low production_of_in_scope_polymers, which is for like 80% of the producers the case, but after no_of_assets bigger 20, there is in almost linear increase of production with no_of_assets
  7. total_waste_div_production over rank ranges from 0.3 to 1.0 and is in general like 0.5 (but this we already saw in univariate analysis), the spread is high across all rank, but there is like a very empty band between 0.6 and 0.9 where only 7 producers are
  8. flexible_format_contribution_to_sup_waste over no_of_assets shows similar picture as production over assets, but with wider spread for assets > 20
  9. rigid_format_contribution_to_sup_waste over no_of_assets is surprisingly different from flexible_format over assets, as it is in the beginning more spread toward higher contribution, but after assets > 20, there seems to be a threshold at 1.4, where only a few outliers go beyond, though it is rising until this (fast reached) point
  10. total_contribution_to_sup_waste over no_of_assets does again look similar to flexible_format over assets, since total = flexible + rigid, this means that above 20 assets, flexible is dominant, but below there is a wider spread due to rigid_format
  11. total_waste_div_production over no_of_assets show at low number of assets (<20) a wide spread ranging from 0.3 to 1.0, but above there seems to be stable at around 0.45 ratio -> maybe there are two different sub-populations behind?
  12. with a bigger production_of_in_scope_polymers comes relatively linearly a bigger flexible_format_contribution_to_sup_waste, but most producer have a smaller 3
  13. rigid_format_contribution_to_sup_waste over production_of_in_scope_polymers shows again the cap in rigid_format part not growing beyond 1.3 with production, but also a second tendency in the beginning where a linear behavior of strong growing rigid_format suggest that there might be two sub-populations
  14. total_contribution_to_sup_waste over production_of_in_scope_polymers looks pretty much linear, with a bulk of data points below production < 3
  15. in total_waste_div_production over production_of_in_scope_polymers below production < 3 there are two cluster around 0.45 and 1.0, beyond production > 3 it seems to be stable at 0.5
  16. rigid_format_contribution_to_sup_waste over flexible_format_contribution_to_sup_waste shows the previously observed phänomena, i) with growing flexible_format, rigid_format also start to grow a little but then stays at around 1.2, ii) there is one group that only grows in rigid_format and produce almost no flexible_format
  17. flexible_format_contribution_to_sup_waste over total_contribution_to_sup_waste shows an almost linear increase in flexible_format with total_contribution, but here again we have a group with almost no flexible_format (which means that they only produce rigid_format)
  18. total_waste_div_production over flexible_format_contribution_to_sup_waste shows agani tqwo clusters one around total_waste_div 1.0 and the other around 0.45, and that the higher regions of flexible_format are only ovvupied by a few producers with a ration around 0.47
  19. rigid_format_contribution_to_sup_waste over total_contribution_to_sup_waste only at the beginning rigid format is growing with total_contribution, but it is not really growing beyond 1.3, for the rigid_format only group, there there is a almost linear group
  20. most data points lie in the range total_waste_div < 0.7 and rigid_format < 0.5, for the outliers there are two groups one around ratio 1.0 and one with lower ratio around 0.5
  21. total_waste_div_production over total_contribution_to_sup_waste shows again two groups around 1.0 and 0.45 and a concentration under 0.75 total_contribution
  22. comparing flexible_format and rigid_format over production shows us that flexible_format is growing linearly while rigid stops growing linearly mid way at production = 6, but this growth might be disturbed by two different sub-populations and is expected to be much less strong and capping out earlier
load packages
overview
head(plastic)
summary(plastic)
      rank        polymer_producer    no_of_assets   production_of_in_scope_polymers flexible_format_contribution_to_sup_waste rigid_format_contribution_to_sup_waste
 Min.   :  1.00   Length:100         Min.   : 0.00   Min.   : 0.200                  Min.   :0.000                             Min.   :0.000                         
 1st Qu.: 25.75   Class :character   1st Qu.: 3.00   1st Qu.: 0.500                  1st Qu.:0.100                             1st Qu.:0.100                         
 Median : 50.50   Mode  :character   Median : 6.00   Median : 0.900                  Median :0.200                             Median :0.200                         
 Mean   : 50.50                      Mean   :11.56   Mean   : 1.805                  Mean   :0.538                             Mean   :0.416                         
 3rd Qu.: 75.25                      3rd Qu.:12.25   3rd Qu.: 1.700                  3rd Qu.:0.500                             3rd Qu.:0.500                         
 Max.   :100.00                      Max.   :82.00   Max.   :11.600                  Max.   :4.700                             Max.   :4.500                         
 total_contribution_to_sup_waste total_waste_div_production
 Min.   :0.200                   Min.   :0.3000            
 1st Qu.:0.300                   1st Qu.:0.4300            
 Median :0.450                   Median :0.5000            
 Mean   :0.950                   Mean   :0.5834            
 3rd Qu.:0.925                   3rd Qu.:0.6900            
 Max.   :5.900                   Max.   :1.0000            
multivariate rank + no_of_assets

no_of_assets over rank increases only slowly until rank 25, afterwards it starts to increase strongly (compared to before), this is where the outliers come in from no_of_assets distribution, but most assets in not rank 1

# two variables, continuous x, continuous y, show trend and distribution
name = c('rank', 'no_of_assets')
df <- plastic %>% rename(x = rank, y = no_of_assets) %>% select(x, y) %>% mutate(x = -x) # x = -x to show rank as increasing from low to high 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.1), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate rank + production_of_in_scope_polymers

production_of_in_scope_polymers over rank starts to increase again substantially after about rank 25

# two variables, continuous x, continuous y, show trend and distribution
name = c('rank', 'production_of_in_scope_polymers')
df <- plastic %>% rename(x = rank, y = production_of_in_scope_polymers) %>% select(x, y) %>% mutate(x = -x) # x = -x to show rank as increasing from low to high 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.1), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate rank + flexible_format_contribution_to_sup_waste

flexible_format_contribution_to_sup_waste over rank starts to increase again substantially after about rank 25, there are a couple of producers above rank 25 which do not produce flexible_format (like outliers), the spread is very high towards the end

# two variables, continuous x, continuous y, show trend and distribution
name = c('rank', 'flexible_format_contribution_to_sup_waste')
df <- plastic %>% rename(x = rank, y = flexible_format_contribution_to_sup_waste) %>% select(x, y) %>% mutate(x = -x) # x = -x to show rank as increasing from low to high 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.1), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate rank + rigid_format_contribution_to_sup_waste

rigid_format_contribution_to_sup_waste over rank starts to increase again substantially after about rank 25, but compared to flexible_format the spread is not as high (except for one outlier, which is also really low on flexible format), but overall there is less production in rigid_format

# two variables, continuous x, continuous y, show trend and distribution
name = c('rank', 'rigid_format_contribution_to_sup_waste')
df <- plastic %>% rename(x = rank, y = rigid_format_contribution_to_sup_waste) %>% select(x, y) %>% mutate(x = -x) # x = -x to show rank as increasing from low to high 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.1), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate rank + total_contribution_to_sup_waste

total_contribution_to_sup_waste over rank, seems to be oddly stepped, but that is because the rank is directly determined by the total_contribution (there are not independent), again the steep increase starts at rank 25

# two variables, continuous x, continuous y, show trend and distribution
name = c('rank', 'total_contribution_to_sup_waste')
df <- plastic %>% rename(x = rank, y = total_contribution_to_sup_waste) %>% select(x, y) %>% mutate(x = -x) # x = -x to show rank as increasing from low to high 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
Solution may be nonunique
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.1), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate rank + total_waste_div_production

total_waste_div_production over rank ranges from 0.3 to 1.0 and is in general like 0.5 (but this we already saw in univariate analysis), the spread is high across all rank, but there is like a very empty band between 0.6 and 0.9 where only 7 producers are

# two variables, continuous x, continuous y, show trend and distribution
name = c('rank', 'total_waste_div_production')
df <- plastic %>% rename(x = rank, y = total_waste_div_production) %>% select(x, y) %>% mutate(x = -x) # x = -x to show rank as increasing from low to high 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.1), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate no_of_assets + production_of_in_scope_polymers

low no_of_assets seems to also imply low production_of_in_scope_polymers, which is for like 80% of the producers the case, but after no_of_assets bigger 20, there is in almost linear increase of production with no_of_assets

# two variables, continuous x, continuous y, show trend and distribution
name = c('no_of_assets', 'production_of_in_scope_polymers')
df <- plastic %>% rename(x = no_of_assets, y = production_of_in_scope_polymers) %>% select(x, y) 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.1), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate no_of_assets + flexible_format_contribution_to_sup_waste

flexible_format_contribution_to_sup_waste over no_of_assets shows similar picture as production over assets, but with wider spread for assets > 20

# two variables, continuous x, continuous y, show trend and distribution
name = c('no_of_assets', 'flexible_format_contribution_to_sup_waste')
df <- plastic %>% rename(x = no_of_assets, y = flexible_format_contribution_to_sup_waste) %>% select(x, y) 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.1), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate no_of_assets + rigid_format_contribution_to_sup_waste

rigid_format_contribution_to_sup_waste over no_of_assets is surprisingly different from flexible_format over assets, as it is in the beginning more spread towrad higher contribution, but after assets > 20, there seems to be a threshold at 1.4, where only a few outliers go beyond, though it is rising until this (fast reached) point

# two variables, continuous x, continuous y, show trend and distribution
name = c('no_of_assets', 'rigid_format_contribution_to_sup_waste')
df <- plastic %>% rename(x = no_of_assets, y = rigid_format_contribution_to_sup_waste) %>% select(x, y) 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate no_of_assets + total_contribution_to_sup_waste

total_contribution_to_sup_waste over no_of_assets does again look similar to flexible_format over assets, since total = flexible + rigid, this means that above 20 assets, flexible is dominant, but below there is a wider spread dur to rigid_format

# two variables, continuous x, continuous y, show trend and distribution
name = c('no_of_assets', 'total_contribution_to_sup_waste')
df <- plastic %>% rename(x = no_of_assets, y = total_contribution_to_sup_waste) %>% select(x, y) 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate no_of_assets + total_waste_div_production

total_waste_div_production over no_of_assets show at low number of assets (<20) a wide spread ranging from 0.3 to 1.0, but above there seems to be stable at around 0.45 ratio -> maybe there are two different subpopulations behind?

# two variables, continuous x, continuous y, show trend and distribution
name = c('no_of_assets', 'total_waste_div_production')
df <- plastic %>% rename(x = no_of_assets, y = total_waste_div_production) %>% select(x, y) 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate production_of_in_scope_polymers + flexible_format_contribution_to_sup_waste

with a bigger production_of_in_scope_polymers comes relatively linearly a bigger flexible_format_contribution_to_sup_waste, but most producer have a smaller 3

# two variables, continuous x, continuous y, show trend and distribution
name = c('production_of_in_scope_polymers', 'flexible_format_contribution_to_sup_waste')
df <- plastic %>% rename(x = production_of_in_scope_polymers, y = flexible_format_contribution_to_sup_waste) %>% select(x, y) 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate production_of_in_scope_polymers + rigid_format_contribution_to_sup_waste

rigid_format_contribution_to_sup_waste over production_of_in_scope_polymers shows again the cap in rigid_format part not growing beyond 1.3 with production, but also a second tendency in the beginning where a linear behavior of strong growing rigid_format suggest that there might be two sub-populations

# two variables, continuous x, continuous y, show trend and distribution
name = c('production_of_in_scope_polymers', 'rigid_format_contribution_to_sup_waste')
df <- plastic %>% rename(x = production_of_in_scope_polymers, y = rigid_format_contribution_to_sup_waste) %>% select(x, y) 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate production_of_in_scope_polymers + total_contribution_to_sup_waste

total_contribution_to_sup_waste over production_of_in_scope_polymers looks pretty much linear, with a bulk of data points below production < 3

# two variables, continuous x, continuous y, show trend and distribution
name = c('production_of_in_scope_polymers', 'total_contribution_to_sup_waste')
df <- plastic %>% rename(x = production_of_in_scope_polymers, y = total_contribution_to_sup_waste) %>% select(x, y) 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate production_of_in_scope_polymers + total_waste_div_production

in total_waste_div_production over production_of_in_scope_polymers below production < 3 there are two cluster around 0.45 and 1.0, beyond production > 3 it seems to be stable at 0.5

# two variables, continuous x, continuous y, show trend and distribution
name = c('production_of_in_scope_polymers', 'total_waste_div_production')
df <- plastic %>% rename(x = production_of_in_scope_polymers, y = total_waste_div_production) %>% select(x, y) 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate flexible_format_contribution_to_sup_waste + rigid_format_contribution_to_sup_waste

rigid_format_contribution_to_sup_waste over flexible_format_contribution_to_sup_waste shows the previously observed phänomena, i) with growing flexible_format, rigid_format also start to grow a little but then stays at around 1.2, ii) there is one group that only grows in rigid_format and produce almost no flexible_format

# two variables, continuous x, continuous y, show trend and distribution
name = c('flexible_format_contribution_to_sup_waste', 'rigid_format_contribution_to_sup_waste')
df <- plastic %>% rename(x = flexible_format_contribution_to_sup_waste, y = rigid_format_contribution_to_sup_waste) %>% select(x, y) 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate flexible_format_contribution_to_sup_waste + total_contribution_to_sup_waste

flexible_format_contribution_to_sup_waste over total_contribution_to_sup_waste shows an almost linear increase in flexible_format with total_contribution, but here again we have a group with almost no flexible_format (which means that they only produce rigid_format)

# two variables, continuous x, continuous y, show trend and distribution
name = c('total_contribution_to_sup_waste', 'flexible_format_contribution_to_sup_waste')
df <- plastic %>% rename(x = total_contribution_to_sup_waste, y = flexible_format_contribution_to_sup_waste) %>% select(x, y) 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
Solution may be nonunique
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate flexible_format_contribution_to_sup_waste + total_waste_div_production

total_waste_div_production over flexible_format_contribution_to_sup_waste shows agani tqwo clusters one around total_waste_div 1.0 and the other around 0.45, and that the higher regions of flexible_format are only ovvupied by a few producers with a ration around 0.47

# two variables, continuous x, continuous y, show trend and distribution
name = c('flexible_format_contribution_to_sup_waste', 'total_waste_div_production')
df <- plastic %>% rename(x = flexible_format_contribution_to_sup_waste, y = total_waste_div_production) %>% select(x, y) 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate rigid_format_contribution_to_sup_waste + total_contribution_to_sup_waste

rigid_format_contribution_to_sup_waste over total_contribution_to_sup_waste only at the beginning rigid format is growing with total_contribution, but it is not really growing beyond 1.3, for the rigid_format only group, there there is a almost linear group

# two variables, continuous x, continuous y, show trend and distribution
name = c('total_contribution_to_sup_waste', 'rigid_format_contribution_to_sup_waste')
df <- plastic %>% rename(x = total_contribution_to_sup_waste, y = rigid_format_contribution_to_sup_waste) %>% select(x, y) 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate rigid_format_contribution_to_sup_waste + total_waste_div_production

most data points lie in the range total_waste_div < 0.7 and rigid_format < 0.5, for the outliers there are two groups one around ratio 1.0 and one with lower ratio around 0.5

# two variables, continuous x, continuous y, show trend and distribution
name = c('rigid_format_contribution_to_sup_waste', 'total_waste_div_production')
df <- plastic %>% rename(x = rigid_format_contribution_to_sup_waste, y = total_waste_div_production) %>% select(x, y) 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
Solution may be nonunique
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
multivariate total_contribution_to_sup_waste + total_waste_div_production

total_waste_div_production over total_contribution_to_sup_waste shows again two groups around 1.0 and 0.45 and a concentration under 0.75 total_contribution

# two variables, continuous x, continuous y, show trend and distribution
name = c('total_contribution_to_sup_waste', 'total_waste_div_production')
df <- plastic %>% rename(x = total_contribution_to_sup_waste, y = total_waste_div_production) %>% select(x, y) 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
compare flexible_format and rigid_format over production

comparing flexible_format and rigid_format over production shows us that flexible_format is growing linearly while rigid stops growing linearly mid way at production = 6, but this growth might be disturbed by two different sub-populations and is expected to be much less strong and capping out earlier

# three variables, continuous x, two continuous y, show trend and distribution <br> 
name = c('production_of_in_scope_polymers', 'rigid_format_contribution_to_sup_waste', 'flexible_format_contribution_to_sup_waste')
df <- plastic %>% rename(x = production_of_in_scope_polymers, rigid = rigid_format_contribution_to_sup_waste, flexible = flexible_format_contribution_to_sup_waste) %>% select(x, rigid, flexible) %>% pivot_longer(cols = c(flexible,rigid)) %>% rename(y = value)

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y, colour = name)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x, colour = name)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y, colour = name)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y, colour = name)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout() %>% hide_legend()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = paste(name[2], "<br>", name[3], sep=""))) 
Can only have one: config
  
fig
# two variables, continuous x, continuous y, show trend and distribution
name = c('rank', 'no_of_assets')
df <- plastic %>% rename(x = rank, y = no_of_assets) %>% select(x, y) %>% mutate(x = -x) # x = -x to show rank as increasing from low to high 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_smooth() + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout()
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile() + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal()
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.85, 0.15), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.85, 0.15)) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
  
fig
# two variables, continuous x, continuous y, show trend and distribution
name = c('rank', 'total_waste_div_production')
df <- plastic %>% rename(x = rank, y = total_waste_div_production) %>% select(x, y) %>% mutate(x = -x) # x = -x to show rank as increasing from low to high 

# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    # geom_jitter(alpha = 0.5, size = 1) +
    geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
    geom_smooth() + # aids the eye in seeing patterns in the presence of overplotting
    geom_point(alpha = 0.75) + # point geom is used to create scatterplots
    theme_minimal() +
    ggtitle(paste("trend of", name[2], "over", name[1], sep=" ")) 
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
  ggplot(aes(x = x)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    theme_minimal() 
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

y_density_plot <- df %>%
  ggplot(aes(x = y)) +
    stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
    # geom_histogram(binwidth = 1) +
    coord_flip() +
    theme_minimal() 
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
    theme_minimal() 
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# https://ggplot2.tidyverse.org/reference/geom_density_2d.html
density_2d_plot <- df %>%
  ggplot(aes(x = x, y = y)) +
    geom_density_2d(alpha = 0.8, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
    geom_point(alpha = 0) +
    theme_minimal()
density_2d_plot <- ggplotly(density_2d_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))

# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.85, 0.15), shareX = TRUE, shareY = TRUE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, density_2d_plot, margin = 0, widths = c(0.85, 0.15)) %>% layout()
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2)) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
  
fig
LS0tDQp0aXRsZTogImRlc2NyaWJlIGFuZCB2aXN1YWxpemUgcGxhc3RpYyB3YXN0ZSBtYWtlcnMgaW5kZXggZGF0YSAtIG11bHRpdmFyaWF0ZSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCi0tLQ0KcHVycG9zZSBvZiBub3RlYm9vaw0KLS0tDQoNCiAgKC8pIGRlc2NyaWJlICYgdmlzdWFsaXplIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHZhcmlhYmxlcyAobXVsdGl2YXJpYXRlKQ0KICAoLykgZ2F0aGVyIGludGVyZXN0aW5nIG9ic2VydmF0aW9ucyBmb3IgZnVydGhlciBpbnZlc3RpZ2F0aW9uDQogICh4KSBnYXRoZXIgcG9zc2libGUgbmV3IGZlYXR1cmVzIGZvciBleHRyYWN0aW9uDQogIA0KdG9kb3M6DQogICgtKSAuLi4NCiAgDQotLS0NCmluZm9ybWF0aW9uDQotLS0NCg0KbmFtZTogbWFrZW92ZXJtb25kYXlfMjAyMXcyMg0KbGluazogaHR0cHM6Ly9kYXRhLndvcmxkL21ha2VvdmVybW9uZGF5LzIwMjF3MjINCnRpdGxlOiAyMDIxL1cyMjogVGhlIFBsYXN0aWMgV2FzdGUgTWFrZXJzIEluZGV4DQpEYXRhIFNvdXJjZTogW01pbmRlcm9vXShodHRwczovL3d3dy5taW5kZXJvby5vcmcvcGxhc3RpYy13YXN0ZS1tYWtlcnMtaW5kZXgvZGF0YS9pbmRpY2VzL3Byb2R1Y2Vycy8pIGZyb20gMjAxOQ0KICANCi0tLQ0KaW5zaWdodHMgDQotLS0NCg0KICAoISkgYXJlIHRoZXJlIHR3byBkaWZmZXJlbnQgc3ViLXBvcHVsYXRpb25zIGluIHRoZSBkYXRhPyBsaWtlIHR3byBkaWZmZXJlbnQgdHlwZXMgb2YgcHJvZHVjZXJzIHdpdGggZGlmZmVyZW50IGJlaGF2aW9yIHJlZ2FyZGluZyByaWdpZF9mb3JtYXQgYW5kIGZsZXhpYmxlX2Zvcm1hdCBwcm9kdWN0aW9uIA0KICAgICAgLT4gbWF5IGJlIHRoZXJlIGFyZSBwcm9kdWNlcnMgd2l0aCBvbmx5IHJpZ2lkIGZvcm1hdA0KICAgICAgLT4gaWYgZ3JvdXAgaXMgaWRlbnRpZmllZCwgdGhlbiBhZGQgYSB2YXJpYWJsZSB0byB0YWcgdGhlbSBhbmQgbWFrZSB0aGUgcGxvdHMgYWdhaW4gd2l0aCBncm91cCBjb2xvcmluZywgSSB3b25kZXIgaWYgdGhlcmUgYXJlIGFsc28gdGhlIHByb2R1Y2VycyB3aXRoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbiByYXRpb24gMS4wIA0KDQogIChpKSBub19vZl9hc3NldHMgb3ZlciByYW5rIGluY3JlYXNlcyBvbmx5IHNsb3dseSB1bnRpbCByYW5rIDI1LCBhZnRlcndhcmRzIGl0IHN0YXJ0cyB0byBpbmNyZWFzZSBzdHJvbmdseSAoY29tcGFyZWQgdG8gYmVmb3JlKSwgdGhpcyBpcyB3aGVyZSB0aGUgb3V0bGllcnMgY29tZSBpbiBmcm9tIG5vX29mX2Fzc2V0cyAgICAgICBkaXN0cmlidXRpb24sIGJ1dCBtb3N0IGFzc2V0cyBpbiBub3QgcmFuayAxDQogIChpKSBwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzIG92ZXIgcmFuayBzdGFydHMgdG8gaW5jcmVhc2UgYWdhaW4gc3Vic3RhbnRpYWxseSBhZnRlciBhYm91dCByYW5rIDI1DQogIChpKSBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBvdmVyIHJhbmsgc3RhcnRzIHRvIGluY3JlYXNlIGFnYWluIHN1YnN0YW50aWFsbHkgYWZ0ZXIgYWJvdXQgcmFuayAyNSwgdGhlcmUgYXJlIGEgY291cGxlIG9mIHByb2R1Y2VycyBhYm92ZSByYW5rIDI1IHdoaWNoIGRvIG5vdCAgICAgICAgICAgIHByb2R1Y2UgZmxleGlibGVfZm9ybWF0IChsaWtlIG91dGxpZXJzKSwgdGhlIHNwcmVhZCBpcyB2ZXJ5IGhpZ2ggdG93YXJkcyB0aGUgZW5kDQogIChpKSByaWdpZF9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBvdmVyIHJhbmsgc3RhcnRzIHRvIGluY3JlYXNlIGFnYWluIHN1YnN0YW50aWFsbHkgYWZ0ZXIgYWJvdXQgcmFuayAyNSwgYnV0IGNvbXBhcmVkIHRvIGZsZXhpYmxlX2Zvcm1hdCB0aGUgc3ByZWFkIGlzIG5vdCBhcyBoaWdoIChleGNlcHQgICAgICAgIGZvciBvbmUgb3V0bGllciwgd2hpY2ggaXMgYWxzbyByZWFsbHkgbG93IG9uIGZsZXhpYmxlIGZvcm1hdCksIGJ1dCBvdmVyYWxsIHRoZXJlIGlzIGxlc3MgcHJvZHVjdGlvbiBpbiByaWdpZF9mb3JtYXQNCiAgKGkpIHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb3ZlciByYW5rLCBzZWVtcyB0byBiZSBvZGRseSBzdGVwcGVkLCBidXQgdGhhdCBpcyBiZWNhdXNlIHRoZSByYW5rIGlzIGRpcmVjdGx5IGRldGVybWluZWQgYnkgdGhlIHRvdGFsX2NvbnRyaWJ1dGlvbiAodGhlcmUgYXJlIG5vdCBpbmRlcGVuZGVudCksICAgICAgIGFnYWluIHRoZSBzdGVlcCBpbmNyZWFzZSBzdGFydHMgYXQgcmFuayAyNSANCiAgKGkpIGxvdyBub19vZl9hc3NldHMgc2VlbXMgdG8gYWxzbyBpbXBseSBsb3cgcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycywgd2hpY2ggaXMgZm9yIGxpa2UgODAlIG9mIHRoZSBwcm9kdWNlcnMgdGhlIGNhc2UsIGJ1dCBhZnRlciBub19vZl9hc3NldHMgYmlnZ2VyIDIwLCB0aGVyZSBpcyBpbiBhbG1vc3QgICAgICAgbGluZWFyIGluY3JlYXNlIG9mIHByb2R1Y3Rpb24gd2l0aCBub19vZl9hc3NldHMNCiAgKGkpIHRvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uIG92ZXIgcmFuayByYW5nZXMgZnJvbSAwLjMgdG8gMS4wIGFuZCBpcyBpbiBnZW5lcmFsIGxpa2UgMC41IChidXQgdGhpcyB3ZSBhbHJlYWR5IHNhdyBpbiB1bml2YXJpYXRlIGFuYWx5c2lzKSwgdGhlIHNwcmVhZCBpcyBoaWdoIGFjcm9zcyBhbGwgcmFuaywgYnV0ICAgICAgIHRoZXJlIGlzIGxpa2UgYSB2ZXJ5IGVtcHR5IGJhbmQgYmV0d2VlbiAwLjYgYW5kIDAuOSB3aGVyZSBvbmx5IDcgcHJvZHVjZXJzIGFyZQ0KICAoaSkgZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb3ZlciBub19vZl9hc3NldHMgc2hvd3Mgc2ltaWxhciBwaWN0dXJlIGFzIHByb2R1Y3Rpb24gb3ZlciBhc3NldHMsIGJ1dCB3aXRoIHdpZGVyIHNwcmVhZCBmb3IgYXNzZXRzID4gMjANCiAgKGkpIHJpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlIG92ZXIgbm9fb2ZfYXNzZXRzIGlzIHN1cnByaXNpbmdseSBkaWZmZXJlbnQgZnJvbSBmbGV4aWJsZV9mb3JtYXQgb3ZlciBhc3NldHMsIGFzIGl0IGlzIGluIHRoZSBiZWdpbm5pbmcgbW9yZSBzcHJlYWQgdG93YXJkIGhpZ2hlciAgICAgICAgICAgICAgIGNvbnRyaWJ1dGlvbiwgYnV0IGFmdGVyIGFzc2V0cyA+IDIwLCB0aGVyZSBzZWVtcyB0byBiZSBhIHRocmVzaG9sZCBhdCAxLjQsIHdoZXJlIG9ubHkgYSBmZXcgb3V0bGllcnMgZ28gYmV5b25kLCB0aG91Z2ggaXQgaXMgcmlzaW5nIHVudGlsIHRoaXMgKGZhc3QgcmVhY2hlZCkgcG9pbnQNCiAgKGkpIHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb3ZlciBub19vZl9hc3NldHMgZG9lcyBhZ2FpbiBsb29rIHNpbWlsYXIgdG8gZmxleGlibGVfZm9ybWF0IG92ZXIgYXNzZXRzLCBzaW5jZSB0b3RhbCA9IGZsZXhpYmxlICsgcmlnaWQsIHRoaXMgbWVhbnMgdGhhdCBhYm92ZSAyMCBhc3NldHMsICAgICAgICAgICAgIGZsZXhpYmxlIGlzIGRvbWluYW50LCBidXQgYmVsb3cgdGhlcmUgaXMgYSB3aWRlciBzcHJlYWQgZHVlIHRvIHJpZ2lkX2Zvcm1hdA0KICAoaSkgdG90YWxfd2FzdGVfZGl2X3Byb2R1Y3Rpb24gb3ZlciBub19vZl9hc3NldHMgc2hvdyBhdCBsb3cgbnVtYmVyIG9mIGFzc2V0cyAoPDIwKSBhIHdpZGUgc3ByZWFkIHJhbmdpbmcgZnJvbSAwLjMgdG8gMS4wLCBidXQgYWJvdmUgdGhlcmUgc2VlbXMgdG8gYmUgc3RhYmxlIGF0IGFyb3VuZCAwLjQ1IHJhdGlvDQogICAgICAtPiBtYXliZSB0aGVyZSBhcmUgdHdvIGRpZmZlcmVudCBzdWItcG9wdWxhdGlvbnMgYmVoaW5kPw0KICAoaSkgd2l0aCBhIGJpZ2dlciBwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzIGNvbWVzIHJlbGF0aXZlbHkgbGluZWFybHkgYSBiaWdnZXIgZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUsIGJ1dCBtb3N0IHByb2R1Y2VyIGhhdmUgYSBzbWFsbGVyIDMNCiAgKGkpIHJpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlIG92ZXIgcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycyBzaG93cyBhZ2FpbiB0aGUgY2FwIGluIHJpZ2lkX2Zvcm1hdCBwYXJ0IG5vdCBncm93aW5nIGJleW9uZCAxLjMgd2l0aCBwcm9kdWN0aW9uLCBidXQgYWxzbyBhIHNlY29uZCAgICAgICAgIHRlbmRlbmN5IGluIHRoZSBiZWdpbm5pbmcgd2hlcmUgYSBsaW5lYXIgYmVoYXZpb3Igb2Ygc3Ryb25nIGdyb3dpbmcgcmlnaWRfZm9ybWF0IHN1Z2dlc3QgdGhhdCB0aGVyZSBtaWdodCBiZSB0d28gc3ViLXBvcHVsYXRpb25zDQogIChpKSB0b3RhbF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlIG92ZXIgcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycyBsb29rcyBwcmV0dHkgbXVjaCBsaW5lYXIsIHdpdGggYSBidWxrIG9mIGRhdGEgcG9pbnRzIGJlbG93IHByb2R1Y3Rpb24gPCAzDQogIChpKSBpbiB0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbiBvdmVyIHByb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMgYmVsb3cgcHJvZHVjdGlvbiA8IDMgdGhlcmUgYXJlIHR3byBjbHVzdGVyIGFyb3VuZCAwLjQ1IGFuZCAxLjAsIGJleW9uZCBwcm9kdWN0aW9uID4gMyBpdCBzZWVtcyB0byBiZSBzdGFibGUgICAgICAgIGF0IDAuNQ0KICAoaSkgcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb3ZlciBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBzaG93cyB0aGUgcHJldmlvdXNseSBvYnNlcnZlZCBwaMOkbm9tZW5hLCBpKSB3aXRoIGdyb3dpbmcgZmxleGlibGVfZm9ybWF0LCByaWdpZF9mb3JtYXQgICAgICAgICAgYWxzbyBzdGFydCB0byBncm93IGEgbGl0dGxlIGJ1dCB0aGVuIHN0YXlzIGF0IGFyb3VuZCAxLjIsIGlpKSB0aGVyZSBpcyBvbmUgZ3JvdXAgdGhhdCBvbmx5IGdyb3dzIGluIHJpZ2lkX2Zvcm1hdCBhbmQgcHJvZHVjZSBhbG1vc3Qgbm8gZmxleGlibGVfZm9ybWF0DQogIChpKSBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBvdmVyIHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgc2hvd3MgYW4gYWxtb3N0IGxpbmVhciBpbmNyZWFzZSBpbiBmbGV4aWJsZV9mb3JtYXQgd2l0aCB0b3RhbF9jb250cmlidXRpb24sIGJ1dCBoZXJlIGFnYWluIHdlICAgICAgICAgIGhhdmUgYSBncm91cCB3aXRoIGFsbW9zdCBubyBmbGV4aWJsZV9mb3JtYXQgKHdoaWNoIG1lYW5zIHRoYXQgdGhleSBvbmx5IHByb2R1Y2UgcmlnaWRfZm9ybWF0KQ0KICAoaSkgdG90YWxfd2FzdGVfZGl2X3Byb2R1Y3Rpb24gb3ZlciBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBzaG93cyBhZ2FuaSB0cXdvIGNsdXN0ZXJzIG9uZSBhcm91bmQgdG90YWxfd2FzdGVfZGl2IDEuMCBhbmQgdGhlIG90aGVyIGFyb3VuZCAwLjQ1LCBhbmQgdGhhdCB0aGUgICAgICAgICAgICBoaWdoZXIgcmVnaW9ucyBvZiBmbGV4aWJsZV9mb3JtYXQgYXJlIG9ubHkgb3Z2dXBpZWQgYnkgYSBmZXcgcHJvZHVjZXJzIHdpdGggYSByYXRpb24gYXJvdW5kIDAuNDcgDQogIChpKSByaWdpZF9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBvdmVyIHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb25seSBhdCB0aGUgYmVnaW5uaW5nIHJpZ2lkIGZvcm1hdCBpcyBncm93aW5nIHdpdGggdG90YWxfY29udHJpYnV0aW9uLCBidXQgaXQgaXMgbm90IHJlYWxseSBncm93aW5nICAgICAgIGJleW9uZCAxLjMsIGZvciB0aGUgcmlnaWRfZm9ybWF0IG9ubHkgZ3JvdXAsIHRoZXJlIHRoZXJlIGlzIGEgYWxtb3N0IGxpbmVhciBncm91cA0KICAoaSkgbW9zdCBkYXRhIHBvaW50cyBsaWUgaW4gdGhlIHJhbmdlIHRvdGFsX3dhc3RlX2RpdiA8IDAuNyBhbmQgcmlnaWRfZm9ybWF0IDwgMC41LCBmb3IgdGhlIG91dGxpZXJzIHRoZXJlIGFyZSB0d28gZ3JvdXBzIG9uZSBhcm91bmQgcmF0aW8gMS4wIGFuZCBvbmUgd2l0aCBsb3dlciByYXRpbyBhcm91bmQgMC41DQogIChpKSB0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbiBvdmVyIHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgc2hvd3MgYWdhaW4gdHdvIGdyb3VwcyBhcm91bmQgMS4wIGFuZCAwLjQ1IGFuZCBhIGNvbmNlbnRyYXRpb24gdW5kZXIgMC43NSB0b3RhbF9jb250cmlidXRpb24NCiAgKGkpIGNvbXBhcmluZyBmbGV4aWJsZV9mb3JtYXQgYW5kIHJpZ2lkX2Zvcm1hdCBvdmVyIHByb2R1Y3Rpb24gc2hvd3MgdXMgdGhhdCBmbGV4aWJsZV9mb3JtYXQgaXMgZ3Jvd2luZyBsaW5lYXJseSB3aGlsZSByaWdpZCBzdG9wcyBncm93aW5nIGxpbmVhcmx5IG1pZCB3YXkgYXQgcHJvZHVjdGlvbiA9IDYsIGJ1dCAgICAgICAgdGhpcyBncm93dGggbWlnaHQgYmUgZGlzdHVyYmVkIGJ5IHR3byBkaWZmZXJlbnQgc3ViLXBvcHVsYXRpb25zIGFuZCBpcyBleHBlY3RlZCB0byBiZSBtdWNoIGxlc3Mgc3Ryb25nIGFuZCBjYXBwaW5nIG91dCBlYXJsaWVyIA0KICANCi0tLQ0KbG9hZCBwYWNrYWdlcw0KLS0tDQpgYGB7ciBsb2FkIHBhY2thZ2VzLCBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKSAjIHRpZHkgZGF0YSBmcmFtZQ0KbGlicmFyeShnZ3RoZW1lcykgIyBmb3IgZXh0cmEgcGxvdCB0aGVtZXMNCmxpYnJhcnkocGxvdGx5KSAjIG1ha2UgZ2dwbG90cyBpbnRlcmFjdGl2ZQ0KbGlicmFyeShsdWJyaWRhdGUpICMgZnVuY3Rpb25zIHRvIHdvcmsgd2l0aCBkYXRlLXRpbWVzIGFuZCB0aW1lLXNwYW5zDQoNCmxpYnJhcnkoY29ycnBsb3QpICMgY29ycmVsYXRpb24gcGxvdHMNCmxpYnJhcnkoZ2dtb3NhaWMpICMgZ2VvbV9tb3NhaWMoKSBtb3NhaWMgcGxvdHMgZm9yIGNhdGVnb3JpY2FsIGRhdGENCmxpYnJhcnkoZ2dwYXJhbGxlbCkgIyBwYXJhbGxlbCBjb29yZGluYXRlIHBsb3RzIGZvciBjYXRlZ29yaWNhbCBkYXRhDQpsaWJyYXJ5KGdnRXh0cmEpICMgY29sbGVjdGlvbiBvZiBmdW5jdGlvbnMgYW5kIGxheWVycyB0byBlbmhhbmNlIGdncGxvdDIsIGxpa2UgZ2dNYXJnaW5hbA0KYGBgDQoNCi0tLQ0Kb3ZlcnZpZXcNCi0tLQ0KYGBge3J9DQpoZWFkKHBsYXN0aWMpDQpgYGANCmBgYHtyfQ0Kc3VtbWFyeShwbGFzdGljKQ0KYGBgDQoNCi0tLQ0KbXVsdGl2YXJpYXRlIHJhbmsgKyBub19vZl9hc3NldHMNCi0tLQ0Kbm9fb2ZfYXNzZXRzIG92ZXIgcmFuayBpbmNyZWFzZXMgb25seSBzbG93bHkgdW50aWwgcmFuayAyNSwgYWZ0ZXJ3YXJkcyBpdCBzdGFydHMgdG8gaW5jcmVhc2Ugc3Ryb25nbHkgKGNvbXBhcmVkIHRvIGJlZm9yZSksIHRoaXMgaXMgd2hlcmUgdGhlIG91dGxpZXJzIGNvbWUgaW4gZnJvbSBub19vZl9hc3NldHMgZGlzdHJpYnV0aW9uLCBidXQgbW9zdCBhc3NldHMgaW4gbm90IHJhbmsgMQ0KDQpgYGB7cn0NCiMgdHdvIHZhcmlhYmxlcywgY29udGludW91cyB4LCBjb250aW51b3VzIHksIHNob3cgdHJlbmQgYW5kIGRpc3RyaWJ1dGlvbg0KbmFtZSA9IGMoJ3JhbmsnLCAnbm9fb2ZfYXNzZXRzJykNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh4ID0gcmFuaywgeSA9IG5vX29mX2Fzc2V0cykgJT4lIHNlbGVjdCh4LCB5KSAlPiUgbXV0YXRlKHggPSAteCkgIyB4ID0gLXggdG8gc2hvdyByYW5rIGFzIGluY3JlYXNpbmcgZnJvbSBsb3cgdG8gaGlnaCANCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9zbW9vdGguaHRtbA0KcG9pbnRfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgIyBnZW9tX2ppdHRlcihhbHBoYSA9IDAuNSwgc2l6ZSA9IDEpICsNCiAgICBnZW9tX3J1ZyhhbHBoYSA9IDAuNSkgKyAjIHR3byAxZCBtYXJnaW5hbCBkaXN0cmlidXRpb25zLCBkaXNwbGF5IGluZGl2aWR1YWwgY2FzZXMgc28gYXJlIGJlc3QgdXNlZCB3aXRoIHNtYWxsZXIgZGF0YXNldHMNCiAgICBnZW9tX2RlbnNpdHlfMmQoYWxwaGEgPSAwLjIsIGJpbnMgPSA0KSArIyAyRCBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uIHVzaW5nIE1BU1M6OmtkZTJkKCkgYW5kIGRpc3BsYXkgdGhlIHJlc3VsdHMgd2l0aCBjb250b3Vycw0KICAgIGdlb21fc21vb3RoKGZpbGwgPSAiZ3JleTkwIikgKyAjIGFpZHMgdGhlIGV5ZSBpbiBzZWVpbmcgcGF0dGVybnMgaW4gdGhlIHByZXNlbmNlIG9mIG92ZXJwbG90dGluZw0KICAgIGdlb21fcG9pbnQoYWxwaGEgPSAwLjc1KSArICMgcG9pbnQgZ2VvbSBpcyB1c2VkIHRvIGNyZWF0ZSBzY2F0dGVycGxvdHMNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUocGFzdGUoInRyZW5kIG9mIiwgbmFtZVsyXSwgIm92ZXIiLCBuYW1lWzFdLCBzZXA9IiAiKSkgDQpwb2ludF9wbG90IDwtIGdncGxvdGx5KHBvaW50X3Bsb3QpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UpKQ0KDQp4X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnhfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHhfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQp5X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geSkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeV9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeV9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXVhbnRpbGUuaHRtbA0KcXVhbHRpbGVfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgZ2VvbV9xdWFudGlsZShhbHBoYSA9IDAuOCkgKyAjIGZpdHMgYSBxdWFudGlsZSByZWdyZXNzaW9uIHRvIHRoZSBkYXRhIGFuZCBkcmF3cyB0aGUgZml0dGVkIHF1YW50aWxlcyB3aXRoIGxpbmVzDQogICAgdGhlbWVfbWluaW1hbCgpIA0KcXVhbHRpbGVfcGxvdCA8LSBnZ3Bsb3RseShxdWFsdGlsZV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBtZXJnZSBmaWd1cmVzIGludG8gb25lIHBsb3QsIHZpYSBzdWJwbG90cywgaHR0cHM6Ly9wbG90bHktci5jb20vYXJyYW5naW5nLXZpZXdzLmh0bWwNCnN1YjEgPC0gc3VicGxvdCh4X2RlbnNpdHlfcGxvdCwgcGxvdGx5X2VtcHR5KCksIHBvaW50X3Bsb3QsIHlfZGVuc2l0eV9wbG90LCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuMTUsIDAuODUpLCB3aWR0aHMgPSBjKDAuOSwgMC4xKSwgc2hhcmVYID0gVFJVRSwgc2hhcmVZID0gVFJVRSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCnN1YjIgPC0gc3VicGxvdChxdWFsdGlsZV9wbG90LCBwbG90bHlfZW1wdHkoKSwgbWFyZ2luID0gMCwgd2lkdGhzID0gYygwLjksIDAuMSksIHRpdGxlWCA9IEZBTFNFLCB0aXRsZVkgPSBGQUxTRSkgJT4lIGxheW91dCgpDQpmaWcgPC0gc3VicGxvdChzdWIxLCBzdWIyLCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuOCwgMC4yKSwgc2hhcmVYID0gVFJVRSkgJT4lIGxheW91dCh4YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lWzFdKSwgeWF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsyXSkpDQogIA0KZmlnDQpgYGANCg0KLS0tDQptdWx0aXZhcmlhdGUgcmFuayArIHByb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMNCi0tLQ0KcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycyBvdmVyIHJhbmsgc3RhcnRzIHRvIGluY3JlYXNlIGFnYWluIHN1YnN0YW50aWFsbHkgYWZ0ZXIgYWJvdXQgcmFuayAyNQ0KDQpgYGB7cn0NCiMgdHdvIHZhcmlhYmxlcywgY29udGludW91cyB4LCBjb250aW51b3VzIHksIHNob3cgdHJlbmQgYW5kIGRpc3RyaWJ1dGlvbg0KbmFtZSA9IGMoJ3JhbmsnLCAncHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycycpDQpkZiA8LSBwbGFzdGljICU+JSByZW5hbWUoeCA9IHJhbmssIHkgPSBwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzKSAlPiUgc2VsZWN0KHgsIHkpICU+JSBtdXRhdGUoeCA9IC14KSAjIHggPSAteCB0byBzaG93IHJhbmsgYXMgaW5jcmVhc2luZyBmcm9tIGxvdyB0byBoaWdoIA0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3Ntb290aC5odG1sDQpwb2ludF9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICAjIGdlb21faml0dGVyKGFscGhhID0gMC41LCBzaXplID0gMSkgKw0KICAgIGdlb21fcnVnKGFscGhhID0gMC41KSArICMgdHdvIDFkIG1hcmdpbmFsIGRpc3RyaWJ1dGlvbnMsIGRpc3BsYXkgaW5kaXZpZHVhbCBjYXNlcyBzbyBhcmUgYmVzdCB1c2VkIHdpdGggc21hbGxlciBkYXRhc2V0cw0KICAgIGdlb21fZGVuc2l0eV8yZChhbHBoYSA9IDAuMiwgYmlucyA9IDQpICsjIDJEIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRpb24gdXNpbmcgTUFTUzo6a2RlMmQoKSBhbmQgZGlzcGxheSB0aGUgcmVzdWx0cyB3aXRoIGNvbnRvdXJzDQogICAgZ2VvbV9zbW9vdGgoZmlsbCA9ICJncmV5OTAiKSArICMgYWlkcyB0aGUgZXllIGluIHNlZWluZyBwYXR0ZXJucyBpbiB0aGUgcHJlc2VuY2Ugb2Ygb3ZlcnBsb3R0aW5nDQogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNzUpICsgIyBwb2ludCBnZW9tIGlzIHVzZWQgdG8gY3JlYXRlIHNjYXR0ZXJwbG90cw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgZ2d0aXRsZShwYXN0ZSgidHJlbmQgb2YiLCBuYW1lWzJdLCAib3ZlciIsIG5hbWVbMV0sIHNlcD0iICIpKSANCnBvaW50X3Bsb3QgPC0gZ2dwbG90bHkocG9pbnRfcGxvdCkgJT4lIGxheW91dCh4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSkpDQoNCnhfZGVuc2l0eV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4KSkgKw0KICAgIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIikgKyAjIGRyYXdzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlLCB3aGljaCBpcyBhIHNtb290aGVkIHZlcnNpb24gb2YgdGhlIGhpc3RvZ3JhbQ0KICAgICMgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeF9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeF9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCnlfZGVuc2l0eV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5KSkgKw0KICAgIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIikgKyAjIGRyYXdzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlLCB3aGljaCBpcyBhIHNtb290aGVkIHZlcnNpb24gb2YgdGhlIGhpc3RvZ3JhbQ0KICAgICMgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQp5X2RlbnNpdHlfcGxvdCA8LSBnZ3Bsb3RseSh5X2RlbnNpdHlfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9xdWFudGlsZS5odG1sDQpxdWFsdGlsZV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICBnZW9tX3F1YW50aWxlKGFscGhhID0gMC44KSArICMgZml0cyBhIHF1YW50aWxlIHJlZ3Jlc3Npb24gdG8gdGhlIGRhdGEgYW5kIGRyYXdzIHRoZSBmaXR0ZWQgcXVhbnRpbGVzIHdpdGggbGluZXMNCiAgICB0aGVtZV9taW5pbWFsKCkgDQpxdWFsdGlsZV9wbG90IDwtIGdncGxvdGx5KHF1YWx0aWxlX3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIG1lcmdlIGZpZ3VyZXMgaW50byBvbmUgcGxvdCwgdmlhIHN1YnBsb3RzLCBodHRwczovL3Bsb3RseS1yLmNvbS9hcnJhbmdpbmctdmlld3MuaHRtbA0Kc3ViMSA8LSBzdWJwbG90KHhfZGVuc2l0eV9wbG90LCBwbG90bHlfZW1wdHkoKSwgcG9pbnRfcGxvdCwgeV9kZW5zaXR5X3Bsb3QsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC4xNSwgMC44NSksIHdpZHRocyA9IGMoMC45LCAwLjEpLCBzaGFyZVggPSBUUlVFLCBzaGFyZVkgPSBUUlVFLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0Kc3ViMiA8LSBzdWJwbG90KHF1YWx0aWxlX3Bsb3QsIHBsb3RseV9lbXB0eSgpLCBtYXJnaW4gPSAwLCB3aWR0aHMgPSBjKDAuOSwgMC4xKSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCmZpZyA8LSBzdWJwbG90KHN1YjEsIHN1YjIsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC44LCAwLjIpLCBzaGFyZVggPSBUUlVFKSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMV0pLCB5YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lWzJdKSkNCiAgDQpmaWcNCmBgYA0KDQotLS0NCm11bHRpdmFyaWF0ZSByYW5rICsgZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUNCi0tLQ0KZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb3ZlciByYW5rIHN0YXJ0cyB0byBpbmNyZWFzZSBhZ2FpbiBzdWJzdGFudGlhbGx5IGFmdGVyIGFib3V0IHJhbmsgMjUsIHRoZXJlIGFyZSBhIGNvdXBsZSBvZiBwcm9kdWNlcnMgYWJvdmUgcmFuayAyNSB3aGljaCBkbyBub3QgcHJvZHVjZSBmbGV4aWJsZV9mb3JtYXQgKGxpa2Ugb3V0bGllcnMpLCB0aGUgc3ByZWFkIGlzIHZlcnkgaGlnaCB0b3dhcmRzIHRoZSBlbmQNCg0KYGBge3J9DQojIHR3byB2YXJpYWJsZXMsIGNvbnRpbnVvdXMgeCwgY29udGludW91cyB5LCBzaG93IHRyZW5kIGFuZCBkaXN0cmlidXRpb24NCm5hbWUgPSBjKCdyYW5rJywgJ2ZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlJykNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh4ID0gcmFuaywgeSA9IGZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlKSAlPiUgc2VsZWN0KHgsIHkpICU+JSBtdXRhdGUoeCA9IC14KSAjIHggPSAteCB0byBzaG93IHJhbmsgYXMgaW5jcmVhc2luZyBmcm9tIGxvdyB0byBoaWdoIA0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3Ntb290aC5odG1sDQpwb2ludF9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICAjIGdlb21faml0dGVyKGFscGhhID0gMC41LCBzaXplID0gMSkgKw0KICAgIGdlb21fcnVnKGFscGhhID0gMC41KSArICMgdHdvIDFkIG1hcmdpbmFsIGRpc3RyaWJ1dGlvbnMsIGRpc3BsYXkgaW5kaXZpZHVhbCBjYXNlcyBzbyBhcmUgYmVzdCB1c2VkIHdpdGggc21hbGxlciBkYXRhc2V0cw0KICAgIGdlb21fZGVuc2l0eV8yZChhbHBoYSA9IDAuMiwgYmlucyA9IDQpICsjIDJEIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRpb24gdXNpbmcgTUFTUzo6a2RlMmQoKSBhbmQgZGlzcGxheSB0aGUgcmVzdWx0cyB3aXRoIGNvbnRvdXJzDQogICAgZ2VvbV9zbW9vdGgoZmlsbCA9ICJncmV5OTAiKSArICMgYWlkcyB0aGUgZXllIGluIHNlZWluZyBwYXR0ZXJucyBpbiB0aGUgcHJlc2VuY2Ugb2Ygb3ZlcnBsb3R0aW5nDQogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNzUpICsgIyBwb2ludCBnZW9tIGlzIHVzZWQgdG8gY3JlYXRlIHNjYXR0ZXJwbG90cw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgZ2d0aXRsZShwYXN0ZSgidHJlbmQgb2YiLCBuYW1lWzJdLCAib3ZlciIsIG5hbWVbMV0sIHNlcD0iICIpKSANCnBvaW50X3Bsb3QgPC0gZ2dwbG90bHkocG9pbnRfcGxvdCkgJT4lIGxheW91dCh4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSkpDQoNCnhfZGVuc2l0eV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4KSkgKw0KICAgIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIikgKyAjIGRyYXdzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlLCB3aGljaCBpcyBhIHNtb290aGVkIHZlcnNpb24gb2YgdGhlIGhpc3RvZ3JhbQ0KICAgICMgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeF9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeF9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCnlfZGVuc2l0eV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5KSkgKw0KICAgIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIikgKyAjIGRyYXdzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlLCB3aGljaCBpcyBhIHNtb290aGVkIHZlcnNpb24gb2YgdGhlIGhpc3RvZ3JhbQ0KICAgICMgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQp5X2RlbnNpdHlfcGxvdCA8LSBnZ3Bsb3RseSh5X2RlbnNpdHlfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9xdWFudGlsZS5odG1sDQpxdWFsdGlsZV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICBnZW9tX3F1YW50aWxlKGFscGhhID0gMC44KSArICMgZml0cyBhIHF1YW50aWxlIHJlZ3Jlc3Npb24gdG8gdGhlIGRhdGEgYW5kIGRyYXdzIHRoZSBmaXR0ZWQgcXVhbnRpbGVzIHdpdGggbGluZXMNCiAgICB0aGVtZV9taW5pbWFsKCkgDQpxdWFsdGlsZV9wbG90IDwtIGdncGxvdGx5KHF1YWx0aWxlX3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIG1lcmdlIGZpZ3VyZXMgaW50byBvbmUgcGxvdCwgdmlhIHN1YnBsb3RzLCBodHRwczovL3Bsb3RseS1yLmNvbS9hcnJhbmdpbmctdmlld3MuaHRtbA0Kc3ViMSA8LSBzdWJwbG90KHhfZGVuc2l0eV9wbG90LCBwbG90bHlfZW1wdHkoKSwgcG9pbnRfcGxvdCwgeV9kZW5zaXR5X3Bsb3QsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC4xNSwgMC44NSksIHdpZHRocyA9IGMoMC45LCAwLjEpLCBzaGFyZVggPSBUUlVFLCBzaGFyZVkgPSBUUlVFLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0Kc3ViMiA8LSBzdWJwbG90KHF1YWx0aWxlX3Bsb3QsIHBsb3RseV9lbXB0eSgpLCBtYXJnaW4gPSAwLCB3aWR0aHMgPSBjKDAuOSwgMC4xKSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCmZpZyA8LSBzdWJwbG90KHN1YjEsIHN1YjIsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC44LCAwLjIpLCBzaGFyZVggPSBUUlVFKSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMV0pLCB5YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lWzJdKSkNCiAgDQpmaWcNCmBgYA0KDQotLS0NCm11bHRpdmFyaWF0ZSByYW5rICsgcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUNCi0tLQ0KcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb3ZlciByYW5rIHN0YXJ0cyB0byBpbmNyZWFzZSBhZ2FpbiBzdWJzdGFudGlhbGx5IGFmdGVyIGFib3V0IHJhbmsgMjUsIGJ1dCBjb21wYXJlZCB0byBmbGV4aWJsZV9mb3JtYXQgdGhlIHNwcmVhZCBpcyBub3QgYXMgaGlnaCAoZXhjZXB0IGZvciBvbmUgb3V0bGllciwgd2hpY2ggaXMgYWxzbyByZWFsbHkgbG93IG9uIGZsZXhpYmxlIGZvcm1hdCksIGJ1dCBvdmVyYWxsIHRoZXJlIGlzIGxlc3MgcHJvZHVjdGlvbiBpbiByaWdpZF9mb3JtYXQNCg0KYGBge3J9DQojIHR3byB2YXJpYWJsZXMsIGNvbnRpbnVvdXMgeCwgY29udGludW91cyB5LCBzaG93IHRyZW5kIGFuZCBkaXN0cmlidXRpb24NCm5hbWUgPSBjKCdyYW5rJywgJ3JpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlJykNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh4ID0gcmFuaywgeSA9IHJpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlKSAlPiUgc2VsZWN0KHgsIHkpICU+JSBtdXRhdGUoeCA9IC14KSAjIHggPSAteCB0byBzaG93IHJhbmsgYXMgaW5jcmVhc2luZyBmcm9tIGxvdyB0byBoaWdoIA0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3Ntb290aC5odG1sDQpwb2ludF9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICAjIGdlb21faml0dGVyKGFscGhhID0gMC41LCBzaXplID0gMSkgKw0KICAgIGdlb21fcnVnKGFscGhhID0gMC41KSArICMgdHdvIDFkIG1hcmdpbmFsIGRpc3RyaWJ1dGlvbnMsIGRpc3BsYXkgaW5kaXZpZHVhbCBjYXNlcyBzbyBhcmUgYmVzdCB1c2VkIHdpdGggc21hbGxlciBkYXRhc2V0cw0KICAgIGdlb21fZGVuc2l0eV8yZChhbHBoYSA9IDAuMiwgYmlucyA9IDQpICsjIDJEIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRpb24gdXNpbmcgTUFTUzo6a2RlMmQoKSBhbmQgZGlzcGxheSB0aGUgcmVzdWx0cyB3aXRoIGNvbnRvdXJzDQogICAgZ2VvbV9zbW9vdGgoZmlsbCA9ICJncmV5OTAiKSArICMgYWlkcyB0aGUgZXllIGluIHNlZWluZyBwYXR0ZXJucyBpbiB0aGUgcHJlc2VuY2Ugb2Ygb3ZlcnBsb3R0aW5nDQogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNzUpICsgIyBwb2ludCBnZW9tIGlzIHVzZWQgdG8gY3JlYXRlIHNjYXR0ZXJwbG90cw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgZ2d0aXRsZShwYXN0ZSgidHJlbmQgb2YiLCBuYW1lWzJdLCAib3ZlciIsIG5hbWVbMV0sIHNlcD0iICIpKSANCnBvaW50X3Bsb3QgPC0gZ2dwbG90bHkocG9pbnRfcGxvdCkgJT4lIGxheW91dCh4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSkpDQoNCnhfZGVuc2l0eV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4KSkgKw0KICAgIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIikgKyAjIGRyYXdzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlLCB3aGljaCBpcyBhIHNtb290aGVkIHZlcnNpb24gb2YgdGhlIGhpc3RvZ3JhbQ0KICAgICMgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeF9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeF9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCnlfZGVuc2l0eV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5KSkgKw0KICAgIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIikgKyAjIGRyYXdzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlLCB3aGljaCBpcyBhIHNtb290aGVkIHZlcnNpb24gb2YgdGhlIGhpc3RvZ3JhbQ0KICAgICMgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQp5X2RlbnNpdHlfcGxvdCA8LSBnZ3Bsb3RseSh5X2RlbnNpdHlfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9xdWFudGlsZS5odG1sDQpxdWFsdGlsZV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICBnZW9tX3F1YW50aWxlKGFscGhhID0gMC44KSArICMgZml0cyBhIHF1YW50aWxlIHJlZ3Jlc3Npb24gdG8gdGhlIGRhdGEgYW5kIGRyYXdzIHRoZSBmaXR0ZWQgcXVhbnRpbGVzIHdpdGggbGluZXMNCiAgICB0aGVtZV9taW5pbWFsKCkgDQpxdWFsdGlsZV9wbG90IDwtIGdncGxvdGx5KHF1YWx0aWxlX3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIG1lcmdlIGZpZ3VyZXMgaW50byBvbmUgcGxvdCwgdmlhIHN1YnBsb3RzLCBodHRwczovL3Bsb3RseS1yLmNvbS9hcnJhbmdpbmctdmlld3MuaHRtbA0Kc3ViMSA8LSBzdWJwbG90KHhfZGVuc2l0eV9wbG90LCBwbG90bHlfZW1wdHkoKSwgcG9pbnRfcGxvdCwgeV9kZW5zaXR5X3Bsb3QsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC4xNSwgMC44NSksIHdpZHRocyA9IGMoMC45LCAwLjEpLCBzaGFyZVggPSBUUlVFLCBzaGFyZVkgPSBUUlVFLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0Kc3ViMiA8LSBzdWJwbG90KHF1YWx0aWxlX3Bsb3QsIHBsb3RseV9lbXB0eSgpLCBtYXJnaW4gPSAwLCB3aWR0aHMgPSBjKDAuOSwgMC4xKSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCmZpZyA8LSBzdWJwbG90KHN1YjEsIHN1YjIsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC44LCAwLjIpLCBzaGFyZVggPSBUUlVFKSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMV0pLCB5YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lWzJdKSkNCiAgDQpmaWcNCmBgYA0KDQotLS0NCm11bHRpdmFyaWF0ZSByYW5rICsgdG90YWxfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZQ0KLS0tDQp0b3RhbF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlIG92ZXIgcmFuaywgc2VlbXMgdG8gYmUgb2RkbHkgc3RlcHBlZCwgYnV0IHRoYXQgaXMgYmVjYXVzZSB0aGUgcmFuayBpcyBkaXJlY3RseSBkZXRlcm1pbmVkIGJ5IHRoZSB0b3RhbF9jb250cmlidXRpb24gKHRoZXJlIGFyZSBub3QgaW5kZXBlbmRlbnQpLCBhZ2FpbiB0aGUgc3RlZXAgaW5jcmVhc2Ugc3RhcnRzIGF0IHJhbmsgMjUgDQoNCmBgYHtyfQ0KIyB0d28gdmFyaWFibGVzLCBjb250aW51b3VzIHgsIGNvbnRpbnVvdXMgeSwgc2hvdyB0cmVuZCBhbmQgZGlzdHJpYnV0aW9uDQpuYW1lID0gYygncmFuaycsICd0b3RhbF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlJykNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh4ID0gcmFuaywgeSA9IHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUpICU+JSBzZWxlY3QoeCwgeSkgJT4lIG11dGF0ZSh4ID0gLXgpICMgeCA9IC14IHRvIHNob3cgcmFuayBhcyBpbmNyZWFzaW5nIGZyb20gbG93IHRvIGhpZ2ggDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fc21vb3RoLmh0bWwNCnBvaW50X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgICMgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjUsIHNpemUgPSAxKSArDQogICAgZ2VvbV9ydWcoYWxwaGEgPSAwLjUpICsgIyB0d28gMWQgbWFyZ2luYWwgZGlzdHJpYnV0aW9ucywgZGlzcGxheSBpbmRpdmlkdWFsIGNhc2VzIHNvIGFyZSBiZXN0IHVzZWQgd2l0aCBzbWFsbGVyIGRhdGFzZXRzDQogICAgZ2VvbV9kZW5zaXR5XzJkKGFscGhhID0gMC4yLCBiaW5zID0gNCkgKyMgMkQga2VybmVsIGRlbnNpdHkgZXN0aW1hdGlvbiB1c2luZyBNQVNTOjprZGUyZCgpIGFuZCBkaXNwbGF5IHRoZSByZXN1bHRzIHdpdGggY29udG91cnMNCiAgICBnZW9tX3Ntb290aChmaWxsID0gImdyZXk5MCIpICsgIyBhaWRzIHRoZSBleWUgaW4gc2VlaW5nIHBhdHRlcm5zIGluIHRoZSBwcmVzZW5jZSBvZiBvdmVycGxvdHRpbmcNCiAgICBnZW9tX3BvaW50KGFscGhhID0gMC43NSkgKyAjIHBvaW50IGdlb20gaXMgdXNlZCB0byBjcmVhdGUgc2NhdHRlcnBsb3RzDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJ0cmVuZCBvZiIsIG5hbWVbMl0sICJvdmVyIiwgbmFtZVsxXSwgc2VwPSIgIikpIA0KcG9pbnRfcGxvdCA8LSBnZ3Bsb3RseShwb2ludF9wbG90KSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFKSkNCg0KeF9kZW5zaXR5X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgpKSArDQogICAgc3RhdF9kZW5zaXR5KGdlb209ImxpbmUiKSArICMgZHJhd3Mga2VybmVsIGRlbnNpdHkgZXN0aW1hdGUsIHdoaWNoIGlzIGEgc21vb3RoZWQgdmVyc2lvbiBvZiB0aGUgaGlzdG9ncmFtDQogICAgIyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQp4X2RlbnNpdHlfcGxvdCA8LSBnZ3Bsb3RseSh4X2RlbnNpdHlfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KeV9kZW5zaXR5X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHkpKSArDQogICAgc3RhdF9kZW5zaXR5KGdlb209ImxpbmUiKSArICMgZHJhd3Mga2VybmVsIGRlbnNpdHkgZXN0aW1hdGUsIHdoaWNoIGlzIGEgc21vb3RoZWQgdmVyc2lvbiBvZiB0aGUgaGlzdG9ncmFtDQogICAgIyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnlfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHlfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3F1YW50aWxlLmh0bWwNCnF1YWx0aWxlX3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgIGdlb21fcXVhbnRpbGUoYWxwaGEgPSAwLjgpICsgIyBmaXRzIGEgcXVhbnRpbGUgcmVncmVzc2lvbiB0byB0aGUgZGF0YSBhbmQgZHJhd3MgdGhlIGZpdHRlZCBxdWFudGlsZXMgd2l0aCBsaW5lcw0KICAgIHRoZW1lX21pbmltYWwoKSANCnF1YWx0aWxlX3Bsb3QgPC0gZ2dwbG90bHkocXVhbHRpbGVfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgbWVyZ2UgZmlndXJlcyBpbnRvIG9uZSBwbG90LCB2aWEgc3VicGxvdHMsIGh0dHBzOi8vcGxvdGx5LXIuY29tL2FycmFuZ2luZy12aWV3cy5odG1sDQpzdWIxIDwtIHN1YnBsb3QoeF9kZW5zaXR5X3Bsb3QsIHBsb3RseV9lbXB0eSgpLCBwb2ludF9wbG90LCB5X2RlbnNpdHlfcGxvdCwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjE1LCAwLjg1KSwgd2lkdGhzID0gYygwLjksIDAuMSksIHNoYXJlWCA9IFRSVUUsIHNoYXJlWSA9IFRSVUUsIHRpdGxlWCA9IEZBTFNFLCB0aXRsZVkgPSBGQUxTRSkgJT4lIGxheW91dCgpDQpzdWIyIDwtIHN1YnBsb3QocXVhbHRpbGVfcGxvdCwgcGxvdGx5X2VtcHR5KCksIG1hcmdpbiA9IDAsIHdpZHRocyA9IGMoMC45LCAwLjEpLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0KZmlnIDwtIHN1YnBsb3Qoc3ViMSwgc3ViMiwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjgsIDAuMiksIHNoYXJlWCA9IFRSVUUpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsxXSksIHlheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMl0pKQ0KICANCmZpZw0KYGBgDQoNCi0tLQ0KbXVsdGl2YXJpYXRlIHJhbmsgKyB0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbg0KLS0tDQp0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbiBvdmVyIHJhbmsgcmFuZ2VzIGZyb20gMC4zIHRvIDEuMCBhbmQgaXMgaW4gZ2VuZXJhbCBsaWtlIDAuNSAoYnV0IHRoaXMgd2UgYWxyZWFkeSBzYXcgaW4gdW5pdmFyaWF0ZSBhbmFseXNpcyksIHRoZSBzcHJlYWQgaXMgaGlnaCBhY3Jvc3MgYWxsIHJhbmssIGJ1dCB0aGVyZSBpcyBsaWtlIGEgdmVyeSBlbXB0eSBiYW5kIGJldHdlZW4gMC42IGFuZCAwLjkgd2hlcmUgb25seSA3IHByb2R1Y2VycyBhcmUNCg0KYGBge3J9DQojIHR3byB2YXJpYWJsZXMsIGNvbnRpbnVvdXMgeCwgY29udGludW91cyB5LCBzaG93IHRyZW5kIGFuZCBkaXN0cmlidXRpb24NCm5hbWUgPSBjKCdyYW5rJywgJ3RvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uJykNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh4ID0gcmFuaywgeSA9IHRvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uKSAlPiUgc2VsZWN0KHgsIHkpICU+JSBtdXRhdGUoeCA9IC14KSAjIHggPSAteCB0byBzaG93IHJhbmsgYXMgaW5jcmVhc2luZyBmcm9tIGxvdyB0byBoaWdoIA0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3Ntb290aC5odG1sDQpwb2ludF9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICAjIGdlb21faml0dGVyKGFscGhhID0gMC41LCBzaXplID0gMSkgKw0KICAgIGdlb21fcnVnKGFscGhhID0gMC41KSArICMgdHdvIDFkIG1hcmdpbmFsIGRpc3RyaWJ1dGlvbnMsIGRpc3BsYXkgaW5kaXZpZHVhbCBjYXNlcyBzbyBhcmUgYmVzdCB1c2VkIHdpdGggc21hbGxlciBkYXRhc2V0cw0KICAgIGdlb21fZGVuc2l0eV8yZChhbHBoYSA9IDAuMiwgYmlucyA9IDQpICsjIDJEIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRpb24gdXNpbmcgTUFTUzo6a2RlMmQoKSBhbmQgZGlzcGxheSB0aGUgcmVzdWx0cyB3aXRoIGNvbnRvdXJzDQogICAgZ2VvbV9zbW9vdGgoZmlsbCA9ICJncmV5OTAiKSArICMgYWlkcyB0aGUgZXllIGluIHNlZWluZyBwYXR0ZXJucyBpbiB0aGUgcHJlc2VuY2Ugb2Ygb3ZlcnBsb3R0aW5nDQogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNzUpICsgIyBwb2ludCBnZW9tIGlzIHVzZWQgdG8gY3JlYXRlIHNjYXR0ZXJwbG90cw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgZ2d0aXRsZShwYXN0ZSgidHJlbmQgb2YiLCBuYW1lWzJdLCAib3ZlciIsIG5hbWVbMV0sIHNlcD0iICIpKSANCnBvaW50X3Bsb3QgPC0gZ2dwbG90bHkocG9pbnRfcGxvdCkgJT4lIGxheW91dCh4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSkpDQoNCnhfZGVuc2l0eV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4KSkgKw0KICAgIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIikgKyAjIGRyYXdzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlLCB3aGljaCBpcyBhIHNtb290aGVkIHZlcnNpb24gb2YgdGhlIGhpc3RvZ3JhbQ0KICAgICMgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeF9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeF9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCnlfZGVuc2l0eV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5KSkgKw0KICAgIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIikgKyAjIGRyYXdzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlLCB3aGljaCBpcyBhIHNtb290aGVkIHZlcnNpb24gb2YgdGhlIGhpc3RvZ3JhbQ0KICAgICMgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQp5X2RlbnNpdHlfcGxvdCA8LSBnZ3Bsb3RseSh5X2RlbnNpdHlfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9xdWFudGlsZS5odG1sDQpxdWFsdGlsZV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICBnZW9tX3F1YW50aWxlKGFscGhhID0gMC44KSArICMgZml0cyBhIHF1YW50aWxlIHJlZ3Jlc3Npb24gdG8gdGhlIGRhdGEgYW5kIGRyYXdzIHRoZSBmaXR0ZWQgcXVhbnRpbGVzIHdpdGggbGluZXMNCiAgICB0aGVtZV9taW5pbWFsKCkgDQpxdWFsdGlsZV9wbG90IDwtIGdncGxvdGx5KHF1YWx0aWxlX3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIG1lcmdlIGZpZ3VyZXMgaW50byBvbmUgcGxvdCwgdmlhIHN1YnBsb3RzLCBodHRwczovL3Bsb3RseS1yLmNvbS9hcnJhbmdpbmctdmlld3MuaHRtbA0Kc3ViMSA8LSBzdWJwbG90KHhfZGVuc2l0eV9wbG90LCBwbG90bHlfZW1wdHkoKSwgcG9pbnRfcGxvdCwgeV9kZW5zaXR5X3Bsb3QsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC4xNSwgMC44NSksIHdpZHRocyA9IGMoMC45LCAwLjEpLCBzaGFyZVggPSBUUlVFLCBzaGFyZVkgPSBUUlVFLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0Kc3ViMiA8LSBzdWJwbG90KHF1YWx0aWxlX3Bsb3QsIHBsb3RseV9lbXB0eSgpLCBtYXJnaW4gPSAwLCB3aWR0aHMgPSBjKDAuOSwgMC4xKSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCmZpZyA8LSBzdWJwbG90KHN1YjEsIHN1YjIsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC44LCAwLjIpLCBzaGFyZVggPSBUUlVFKSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMV0pLCB5YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lWzJdKSkNCiAgDQpmaWcNCmBgYA0KDQotLS0NCm11bHRpdmFyaWF0ZSBub19vZl9hc3NldHMgKyBwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzDQotLS0NCmxvdyBub19vZl9hc3NldHMgc2VlbXMgdG8gYWxzbyBpbXBseSBsb3cgcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycywgd2hpY2ggaXMgZm9yIGxpa2UgODAlIG9mIHRoZSBwcm9kdWNlcnMgdGhlIGNhc2UsIGJ1dCBhZnRlciBub19vZl9hc3NldHMgYmlnZ2VyIDIwLCB0aGVyZSBpcyBpbiBhbG1vc3QgbGluZWFyIGluY3JlYXNlIG9mIHByb2R1Y3Rpb24gd2l0aCBub19vZl9hc3NldHMNCg0KYGBge3J9DQojIHR3byB2YXJpYWJsZXMsIGNvbnRpbnVvdXMgeCwgY29udGludW91cyB5LCBzaG93IHRyZW5kIGFuZCBkaXN0cmlidXRpb24NCm5hbWUgPSBjKCdub19vZl9hc3NldHMnLCAncHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycycpDQpkZiA8LSBwbGFzdGljICU+JSByZW5hbWUoeCA9IG5vX29mX2Fzc2V0cywgeSA9IHByb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMpICU+JSBzZWxlY3QoeCwgeSkgDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fc21vb3RoLmh0bWwNCnBvaW50X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgICMgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjUsIHNpemUgPSAxKSArDQogICAgZ2VvbV9ydWcoYWxwaGEgPSAwLjUpICsgIyB0d28gMWQgbWFyZ2luYWwgZGlzdHJpYnV0aW9ucywgZGlzcGxheSBpbmRpdmlkdWFsIGNhc2VzIHNvIGFyZSBiZXN0IHVzZWQgd2l0aCBzbWFsbGVyIGRhdGFzZXRzDQogICAgZ2VvbV9kZW5zaXR5XzJkKGFscGhhID0gMC4yLCBiaW5zID0gNCkgKyMgMkQga2VybmVsIGRlbnNpdHkgZXN0aW1hdGlvbiB1c2luZyBNQVNTOjprZGUyZCgpIGFuZCBkaXNwbGF5IHRoZSByZXN1bHRzIHdpdGggY29udG91cnMNCiAgICBnZW9tX3Ntb290aChmaWxsID0gImdyZXk5MCIpICsgIyBhaWRzIHRoZSBleWUgaW4gc2VlaW5nIHBhdHRlcm5zIGluIHRoZSBwcmVzZW5jZSBvZiBvdmVycGxvdHRpbmcNCiAgICBnZW9tX3BvaW50KGFscGhhID0gMC43NSkgKyAjIHBvaW50IGdlb20gaXMgdXNlZCB0byBjcmVhdGUgc2NhdHRlcnBsb3RzDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJ0cmVuZCBvZiIsIG5hbWVbMl0sICJvdmVyIiwgbmFtZVsxXSwgc2VwPSIgIikpIA0KcG9pbnRfcGxvdCA8LSBnZ3Bsb3RseShwb2ludF9wbG90KSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFKSkNCg0KeF9kZW5zaXR5X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgpKSArDQogICAgc3RhdF9kZW5zaXR5KGdlb209ImxpbmUiKSArICMgZHJhd3Mga2VybmVsIGRlbnNpdHkgZXN0aW1hdGUsIHdoaWNoIGlzIGEgc21vb3RoZWQgdmVyc2lvbiBvZiB0aGUgaGlzdG9ncmFtDQogICAgIyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQp4X2RlbnNpdHlfcGxvdCA8LSBnZ3Bsb3RseSh4X2RlbnNpdHlfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KeV9kZW5zaXR5X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHkpKSArDQogICAgc3RhdF9kZW5zaXR5KGdlb209ImxpbmUiKSArICMgZHJhd3Mga2VybmVsIGRlbnNpdHkgZXN0aW1hdGUsIHdoaWNoIGlzIGEgc21vb3RoZWQgdmVyc2lvbiBvZiB0aGUgaGlzdG9ncmFtDQogICAgIyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnlfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHlfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3F1YW50aWxlLmh0bWwNCnF1YWx0aWxlX3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgIGdlb21fcXVhbnRpbGUoYWxwaGEgPSAwLjgpICsgIyBmaXRzIGEgcXVhbnRpbGUgcmVncmVzc2lvbiB0byB0aGUgZGF0YSBhbmQgZHJhd3MgdGhlIGZpdHRlZCBxdWFudGlsZXMgd2l0aCBsaW5lcw0KICAgIHRoZW1lX21pbmltYWwoKSANCnF1YWx0aWxlX3Bsb3QgPC0gZ2dwbG90bHkocXVhbHRpbGVfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgbWVyZ2UgZmlndXJlcyBpbnRvIG9uZSBwbG90LCB2aWEgc3VicGxvdHMsIGh0dHBzOi8vcGxvdGx5LXIuY29tL2FycmFuZ2luZy12aWV3cy5odG1sDQpzdWIxIDwtIHN1YnBsb3QoeF9kZW5zaXR5X3Bsb3QsIHBsb3RseV9lbXB0eSgpLCBwb2ludF9wbG90LCB5X2RlbnNpdHlfcGxvdCwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjE1LCAwLjg1KSwgd2lkdGhzID0gYygwLjksIDAuMSksIHNoYXJlWCA9IFRSVUUsIHNoYXJlWSA9IFRSVUUsIHRpdGxlWCA9IEZBTFNFLCB0aXRsZVkgPSBGQUxTRSkgJT4lIGxheW91dCgpDQpzdWIyIDwtIHN1YnBsb3QocXVhbHRpbGVfcGxvdCwgcGxvdGx5X2VtcHR5KCksIG1hcmdpbiA9IDAsIHdpZHRocyA9IGMoMC45LCAwLjEpLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0KZmlnIDwtIHN1YnBsb3Qoc3ViMSwgc3ViMiwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjgsIDAuMiksIHNoYXJlWCA9IFRSVUUpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsxXSksIHlheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMl0pKQ0KICANCmZpZw0KYGBgDQoNCi0tLQ0KbXVsdGl2YXJpYXRlIG5vX29mX2Fzc2V0cyArIGZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlDQotLS0NCmZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlIG92ZXIgbm9fb2ZfYXNzZXRzIHNob3dzIHNpbWlsYXIgcGljdHVyZSBhcyBwcm9kdWN0aW9uIG92ZXIgYXNzZXRzLCBidXQgd2l0aCB3aWRlciBzcHJlYWQgZm9yIGFzc2V0cyA+IDIwDQoNCmBgYHtyfQ0KIyB0d28gdmFyaWFibGVzLCBjb250aW51b3VzIHgsIGNvbnRpbnVvdXMgeSwgc2hvdyB0cmVuZCBhbmQgZGlzdHJpYnV0aW9uDQpuYW1lID0gYygnbm9fb2ZfYXNzZXRzJywgJ2ZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlJykNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh4ID0gbm9fb2ZfYXNzZXRzLCB5ID0gZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUpICU+JSBzZWxlY3QoeCwgeSkgDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fc21vb3RoLmh0bWwNCnBvaW50X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgICMgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjUsIHNpemUgPSAxKSArDQogICAgZ2VvbV9ydWcoYWxwaGEgPSAwLjUpICsgIyB0d28gMWQgbWFyZ2luYWwgZGlzdHJpYnV0aW9ucywgZGlzcGxheSBpbmRpdmlkdWFsIGNhc2VzIHNvIGFyZSBiZXN0IHVzZWQgd2l0aCBzbWFsbGVyIGRhdGFzZXRzDQogICAgZ2VvbV9kZW5zaXR5XzJkKGFscGhhID0gMC4yLCBiaW5zID0gNCkgKyMgMkQga2VybmVsIGRlbnNpdHkgZXN0aW1hdGlvbiB1c2luZyBNQVNTOjprZGUyZCgpIGFuZCBkaXNwbGF5IHRoZSByZXN1bHRzIHdpdGggY29udG91cnMNCiAgICBnZW9tX3Ntb290aChmaWxsID0gImdyZXk5MCIpICsgIyBhaWRzIHRoZSBleWUgaW4gc2VlaW5nIHBhdHRlcm5zIGluIHRoZSBwcmVzZW5jZSBvZiBvdmVycGxvdHRpbmcNCiAgICBnZW9tX3BvaW50KGFscGhhID0gMC43NSkgKyAjIHBvaW50IGdlb20gaXMgdXNlZCB0byBjcmVhdGUgc2NhdHRlcnBsb3RzDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJ0cmVuZCBvZiIsIG5hbWVbMl0sICJvdmVyIiwgbmFtZVsxXSwgc2VwPSIgIikpIA0KcG9pbnRfcGxvdCA8LSBnZ3Bsb3RseShwb2ludF9wbG90KSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFKSkNCg0KeF9kZW5zaXR5X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgpKSArDQogICAgc3RhdF9kZW5zaXR5KGdlb209ImxpbmUiKSArICMgZHJhd3Mga2VybmVsIGRlbnNpdHkgZXN0aW1hdGUsIHdoaWNoIGlzIGEgc21vb3RoZWQgdmVyc2lvbiBvZiB0aGUgaGlzdG9ncmFtDQogICAgIyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQp4X2RlbnNpdHlfcGxvdCA8LSBnZ3Bsb3RseSh4X2RlbnNpdHlfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KeV9kZW5zaXR5X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHkpKSArDQogICAgc3RhdF9kZW5zaXR5KGdlb209ImxpbmUiKSArICMgZHJhd3Mga2VybmVsIGRlbnNpdHkgZXN0aW1hdGUsIHdoaWNoIGlzIGEgc21vb3RoZWQgdmVyc2lvbiBvZiB0aGUgaGlzdG9ncmFtDQogICAgIyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnlfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHlfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3F1YW50aWxlLmh0bWwNCnF1YWx0aWxlX3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgIGdlb21fcXVhbnRpbGUoYWxwaGEgPSAwLjgpICsgIyBmaXRzIGEgcXVhbnRpbGUgcmVncmVzc2lvbiB0byB0aGUgZGF0YSBhbmQgZHJhd3MgdGhlIGZpdHRlZCBxdWFudGlsZXMgd2l0aCBsaW5lcw0KICAgIHRoZW1lX21pbmltYWwoKSANCnF1YWx0aWxlX3Bsb3QgPC0gZ2dwbG90bHkocXVhbHRpbGVfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgbWVyZ2UgZmlndXJlcyBpbnRvIG9uZSBwbG90LCB2aWEgc3VicGxvdHMsIGh0dHBzOi8vcGxvdGx5LXIuY29tL2FycmFuZ2luZy12aWV3cy5odG1sDQpzdWIxIDwtIHN1YnBsb3QoeF9kZW5zaXR5X3Bsb3QsIHBsb3RseV9lbXB0eSgpLCBwb2ludF9wbG90LCB5X2RlbnNpdHlfcGxvdCwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjE1LCAwLjg1KSwgd2lkdGhzID0gYygwLjksIDAuMSksIHNoYXJlWCA9IFRSVUUsIHNoYXJlWSA9IFRSVUUsIHRpdGxlWCA9IEZBTFNFLCB0aXRsZVkgPSBGQUxTRSkgJT4lIGxheW91dCgpDQpzdWIyIDwtIHN1YnBsb3QocXVhbHRpbGVfcGxvdCwgcGxvdGx5X2VtcHR5KCksIG1hcmdpbiA9IDAsIHdpZHRocyA9IGMoMC45LCAwLjEpLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0KZmlnIDwtIHN1YnBsb3Qoc3ViMSwgc3ViMiwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjgsIDAuMiksIHNoYXJlWCA9IFRSVUUpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsxXSksIHlheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMl0pKQ0KICANCmZpZw0KYGBgDQoNCi0tLQ0KbXVsdGl2YXJpYXRlIG5vX29mX2Fzc2V0cyArIHJpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlDQotLS0NCnJpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlIG92ZXIgbm9fb2ZfYXNzZXRzIGlzIHN1cnByaXNpbmdseSBkaWZmZXJlbnQgZnJvbSBmbGV4aWJsZV9mb3JtYXQgb3ZlciBhc3NldHMsIGFzIGl0IGlzIGluIHRoZSBiZWdpbm5pbmcgbW9yZSBzcHJlYWQgdG93cmFkIGhpZ2hlciBjb250cmlidXRpb24sIGJ1dCBhZnRlciBhc3NldHMgPiAyMCwgdGhlcmUgc2VlbXMgdG8gYmUgYSB0aHJlc2hvbGQgYXQgMS40LCB3aGVyZSBvbmx5IGEgZmV3IG91dGxpZXJzIGdvIGJleW9uZCwgdGhvdWdoIGl0IGlzIHJpc2luZyB1bnRpbCB0aGlzIChmYXN0IHJlYWNoZWQpIHBvaW50DQoNCmBgYHtyfQ0KIyB0d28gdmFyaWFibGVzLCBjb250aW51b3VzIHgsIGNvbnRpbnVvdXMgeSwgc2hvdyB0cmVuZCBhbmQgZGlzdHJpYnV0aW9uDQpuYW1lID0gYygnbm9fb2ZfYXNzZXRzJywgJ3JpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlJykNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh4ID0gbm9fb2ZfYXNzZXRzLCB5ID0gcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUpICU+JSBzZWxlY3QoeCwgeSkgDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fc21vb3RoLmh0bWwNCnBvaW50X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgICMgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjUsIHNpemUgPSAxKSArDQogICAgZ2VvbV9ydWcoYWxwaGEgPSAwLjUpICsgIyB0d28gMWQgbWFyZ2luYWwgZGlzdHJpYnV0aW9ucywgZGlzcGxheSBpbmRpdmlkdWFsIGNhc2VzIHNvIGFyZSBiZXN0IHVzZWQgd2l0aCBzbWFsbGVyIGRhdGFzZXRzDQogICAgZ2VvbV9kZW5zaXR5XzJkKGFscGhhID0gMC4yLCBiaW5zID0gNCkgKyMgMkQga2VybmVsIGRlbnNpdHkgZXN0aW1hdGlvbiB1c2luZyBNQVNTOjprZGUyZCgpIGFuZCBkaXNwbGF5IHRoZSByZXN1bHRzIHdpdGggY29udG91cnMNCiAgICBnZW9tX3Ntb290aChmaWxsID0gImdyZXk5MCIpICsgIyBhaWRzIHRoZSBleWUgaW4gc2VlaW5nIHBhdHRlcm5zIGluIHRoZSBwcmVzZW5jZSBvZiBvdmVycGxvdHRpbmcNCiAgICBnZW9tX3BvaW50KGFscGhhID0gMC43NSkgKyAjIHBvaW50IGdlb20gaXMgdXNlZCB0byBjcmVhdGUgc2NhdHRlcnBsb3RzDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJ0cmVuZCBvZiIsIG5hbWVbMl0sICJvdmVyIiwgbmFtZVsxXSwgc2VwPSIgIikpIA0KcG9pbnRfcGxvdCA8LSBnZ3Bsb3RseShwb2ludF9wbG90KSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFKSkNCg0KeF9kZW5zaXR5X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgpKSArDQogICAgc3RhdF9kZW5zaXR5KGdlb209ImxpbmUiKSArICMgZHJhd3Mga2VybmVsIGRlbnNpdHkgZXN0aW1hdGUsIHdoaWNoIGlzIGEgc21vb3RoZWQgdmVyc2lvbiBvZiB0aGUgaGlzdG9ncmFtDQogICAgIyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQp4X2RlbnNpdHlfcGxvdCA8LSBnZ3Bsb3RseSh4X2RlbnNpdHlfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KeV9kZW5zaXR5X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHkpKSArDQogICAgc3RhdF9kZW5zaXR5KGdlb209ImxpbmUiKSArICMgZHJhd3Mga2VybmVsIGRlbnNpdHkgZXN0aW1hdGUsIHdoaWNoIGlzIGEgc21vb3RoZWQgdmVyc2lvbiBvZiB0aGUgaGlzdG9ncmFtDQogICAgIyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnlfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHlfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3F1YW50aWxlLmh0bWwNCnF1YWx0aWxlX3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgIGdlb21fcXVhbnRpbGUoYWxwaGEgPSAwLjgpICsgIyBmaXRzIGEgcXVhbnRpbGUgcmVncmVzc2lvbiB0byB0aGUgZGF0YSBhbmQgZHJhd3MgdGhlIGZpdHRlZCBxdWFudGlsZXMgd2l0aCBsaW5lcw0KICAgIHRoZW1lX21pbmltYWwoKSANCnF1YWx0aWxlX3Bsb3QgPC0gZ2dwbG90bHkocXVhbHRpbGVfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgbWVyZ2UgZmlndXJlcyBpbnRvIG9uZSBwbG90LCB2aWEgc3VicGxvdHMsIGh0dHBzOi8vcGxvdGx5LXIuY29tL2FycmFuZ2luZy12aWV3cy5odG1sDQpzdWIxIDwtIHN1YnBsb3QoeF9kZW5zaXR5X3Bsb3QsIHBsb3RseV9lbXB0eSgpLCBwb2ludF9wbG90LCB5X2RlbnNpdHlfcGxvdCwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjE1LCAwLjg1KSwgd2lkdGhzID0gYygwLjksIDAuMSksIHNoYXJlWCA9IFRSVUUsIHNoYXJlWSA9IFRSVUUsIHRpdGxlWCA9IEZBTFNFLCB0aXRsZVkgPSBGQUxTRSkgJT4lIGxheW91dCgpDQpzdWIyIDwtIHN1YnBsb3QocXVhbHRpbGVfcGxvdCwgcGxvdGx5X2VtcHR5KCksIG1hcmdpbiA9IDAsIHdpZHRocyA9IGMoMC45LCAwLjEwKSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCmZpZyA8LSBzdWJwbG90KHN1YjEsIHN1YjIsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC44LCAwLjIpLCBzaGFyZVggPSBUUlVFKSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMV0pLCB5YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lWzJdKSkNCiAgDQpmaWcNCmBgYA0KDQotLS0NCm11bHRpdmFyaWF0ZSBub19vZl9hc3NldHMgKyB0b3RhbF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlDQotLS0NCnRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb3ZlciBub19vZl9hc3NldHMgZG9lcyBhZ2FpbiBsb29rIHNpbWlsYXIgdG8gZmxleGlibGVfZm9ybWF0IG92ZXIgYXNzZXRzLCBzaW5jZSB0b3RhbCA9IGZsZXhpYmxlICsgcmlnaWQsIHRoaXMgbWVhbnMgdGhhdCBhYm92ZSAyMCBhc3NldHMsIGZsZXhpYmxlIGlzIGRvbWluYW50LCBidXQgYmVsb3cgdGhlcmUgaXMgYSB3aWRlciBzcHJlYWQgZHVyIHRvIHJpZ2lkX2Zvcm1hdA0KDQpgYGB7cn0NCiMgdHdvIHZhcmlhYmxlcywgY29udGludW91cyB4LCBjb250aW51b3VzIHksIHNob3cgdHJlbmQgYW5kIGRpc3RyaWJ1dGlvbg0KbmFtZSA9IGMoJ25vX29mX2Fzc2V0cycsICd0b3RhbF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlJykNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh4ID0gbm9fb2ZfYXNzZXRzLCB5ID0gdG90YWxfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSkgJT4lIHNlbGVjdCh4LCB5KSANCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9zbW9vdGguaHRtbA0KcG9pbnRfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgIyBnZW9tX2ppdHRlcihhbHBoYSA9IDAuNSwgc2l6ZSA9IDEpICsNCiAgICBnZW9tX3J1ZyhhbHBoYSA9IDAuNSkgKyAjIHR3byAxZCBtYXJnaW5hbCBkaXN0cmlidXRpb25zLCBkaXNwbGF5IGluZGl2aWR1YWwgY2FzZXMgc28gYXJlIGJlc3QgdXNlZCB3aXRoIHNtYWxsZXIgZGF0YXNldHMNCiAgICBnZW9tX2RlbnNpdHlfMmQoYWxwaGEgPSAwLjIsIGJpbnMgPSA0KSArIyAyRCBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uIHVzaW5nIE1BU1M6OmtkZTJkKCkgYW5kIGRpc3BsYXkgdGhlIHJlc3VsdHMgd2l0aCBjb250b3Vycw0KICAgIGdlb21fc21vb3RoKGZpbGwgPSAiZ3JleTkwIikgKyAjIGFpZHMgdGhlIGV5ZSBpbiBzZWVpbmcgcGF0dGVybnMgaW4gdGhlIHByZXNlbmNlIG9mIG92ZXJwbG90dGluZw0KICAgIGdlb21fcG9pbnQoYWxwaGEgPSAwLjc1KSArICMgcG9pbnQgZ2VvbSBpcyB1c2VkIHRvIGNyZWF0ZSBzY2F0dGVycGxvdHMNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUocGFzdGUoInRyZW5kIG9mIiwgbmFtZVsyXSwgIm92ZXIiLCBuYW1lWzFdLCBzZXA9IiAiKSkgDQpwb2ludF9wbG90IDwtIGdncGxvdGx5KHBvaW50X3Bsb3QpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UpKQ0KDQp4X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnhfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHhfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQp5X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geSkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeV9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeV9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXVhbnRpbGUuaHRtbA0KcXVhbHRpbGVfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgZ2VvbV9xdWFudGlsZShhbHBoYSA9IDAuOCkgKyAjIGZpdHMgYSBxdWFudGlsZSByZWdyZXNzaW9uIHRvIHRoZSBkYXRhIGFuZCBkcmF3cyB0aGUgZml0dGVkIHF1YW50aWxlcyB3aXRoIGxpbmVzDQogICAgdGhlbWVfbWluaW1hbCgpIA0KcXVhbHRpbGVfcGxvdCA8LSBnZ3Bsb3RseShxdWFsdGlsZV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBtZXJnZSBmaWd1cmVzIGludG8gb25lIHBsb3QsIHZpYSBzdWJwbG90cywgaHR0cHM6Ly9wbG90bHktci5jb20vYXJyYW5naW5nLXZpZXdzLmh0bWwNCnN1YjEgPC0gc3VicGxvdCh4X2RlbnNpdHlfcGxvdCwgcGxvdGx5X2VtcHR5KCksIHBvaW50X3Bsb3QsIHlfZGVuc2l0eV9wbG90LCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuMTUsIDAuODUpLCB3aWR0aHMgPSBjKDAuOSwgMC4xKSwgc2hhcmVYID0gVFJVRSwgc2hhcmVZID0gVFJVRSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCnN1YjIgPC0gc3VicGxvdChxdWFsdGlsZV9wbG90LCBwbG90bHlfZW1wdHkoKSwgbWFyZ2luID0gMCwgd2lkdGhzID0gYygwLjksIDAuMTApLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0KZmlnIDwtIHN1YnBsb3Qoc3ViMSwgc3ViMiwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjgsIDAuMiksIHNoYXJlWCA9IFRSVUUpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsxXSksIHlheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMl0pKQ0KICANCmZpZw0KYGBgDQoNCi0tLQ0KbXVsdGl2YXJpYXRlIG5vX29mX2Fzc2V0cyArIHRvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uDQotLS0NCnRvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uIG92ZXIgbm9fb2ZfYXNzZXRzIHNob3cgYXQgbG93IG51bWJlciBvZiBhc3NldHMgKDwyMCkgYSB3aWRlIHNwcmVhZCByYW5naW5nIGZyb20gMC4zIHRvIDEuMCwgYnV0IGFib3ZlIHRoZXJlIHNlZW1zIHRvIGJlIHN0YWJsZSBhdCBhcm91bmQgMC40NSByYXRpbw0KLT4gbWF5YmUgdGhlcmUgYXJlIHR3byBkaWZmZXJlbnQgc3VicG9wdWxhdGlvbnMgYmVoaW5kPw0KDQpgYGB7cn0NCiMgdHdvIHZhcmlhYmxlcywgY29udGludW91cyB4LCBjb250aW51b3VzIHksIHNob3cgdHJlbmQgYW5kIGRpc3RyaWJ1dGlvbg0KbmFtZSA9IGMoJ25vX29mX2Fzc2V0cycsICd0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbicpDQpkZiA8LSBwbGFzdGljICU+JSByZW5hbWUoeCA9IG5vX29mX2Fzc2V0cywgeSA9IHRvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uKSAlPiUgc2VsZWN0KHgsIHkpIA0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3Ntb290aC5odG1sDQpwb2ludF9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICAjIGdlb21faml0dGVyKGFscGhhID0gMC41LCBzaXplID0gMSkgKw0KICAgIGdlb21fcnVnKGFscGhhID0gMC41KSArICMgdHdvIDFkIG1hcmdpbmFsIGRpc3RyaWJ1dGlvbnMsIGRpc3BsYXkgaW5kaXZpZHVhbCBjYXNlcyBzbyBhcmUgYmVzdCB1c2VkIHdpdGggc21hbGxlciBkYXRhc2V0cw0KICAgIGdlb21fZGVuc2l0eV8yZChhbHBoYSA9IDAuMiwgYmlucyA9IDQpICsjIDJEIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRpb24gdXNpbmcgTUFTUzo6a2RlMmQoKSBhbmQgZGlzcGxheSB0aGUgcmVzdWx0cyB3aXRoIGNvbnRvdXJzDQogICAgZ2VvbV9zbW9vdGgoZmlsbCA9ICJncmV5OTAiKSArICMgYWlkcyB0aGUgZXllIGluIHNlZWluZyBwYXR0ZXJucyBpbiB0aGUgcHJlc2VuY2Ugb2Ygb3ZlcnBsb3R0aW5nDQogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNzUpICsgIyBwb2ludCBnZW9tIGlzIHVzZWQgdG8gY3JlYXRlIHNjYXR0ZXJwbG90cw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgZ2d0aXRsZShwYXN0ZSgidHJlbmQgb2YiLCBuYW1lWzJdLCAib3ZlciIsIG5hbWVbMV0sIHNlcD0iICIpKSANCnBvaW50X3Bsb3QgPC0gZ2dwbG90bHkocG9pbnRfcGxvdCkgJT4lIGxheW91dCh4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSkpDQoNCnhfZGVuc2l0eV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4KSkgKw0KICAgIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIikgKyAjIGRyYXdzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlLCB3aGljaCBpcyBhIHNtb290aGVkIHZlcnNpb24gb2YgdGhlIGhpc3RvZ3JhbQ0KICAgICMgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeF9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeF9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCnlfZGVuc2l0eV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5KSkgKw0KICAgIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIikgKyAjIGRyYXdzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlLCB3aGljaCBpcyBhIHNtb290aGVkIHZlcnNpb24gb2YgdGhlIGhpc3RvZ3JhbQ0KICAgICMgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQp5X2RlbnNpdHlfcGxvdCA8LSBnZ3Bsb3RseSh5X2RlbnNpdHlfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9xdWFudGlsZS5odG1sDQpxdWFsdGlsZV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICBnZW9tX3F1YW50aWxlKGFscGhhID0gMC44KSArICMgZml0cyBhIHF1YW50aWxlIHJlZ3Jlc3Npb24gdG8gdGhlIGRhdGEgYW5kIGRyYXdzIHRoZSBmaXR0ZWQgcXVhbnRpbGVzIHdpdGggbGluZXMNCiAgICB0aGVtZV9taW5pbWFsKCkgDQpxdWFsdGlsZV9wbG90IDwtIGdncGxvdGx5KHF1YWx0aWxlX3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIG1lcmdlIGZpZ3VyZXMgaW50byBvbmUgcGxvdCwgdmlhIHN1YnBsb3RzLCBodHRwczovL3Bsb3RseS1yLmNvbS9hcnJhbmdpbmctdmlld3MuaHRtbA0Kc3ViMSA8LSBzdWJwbG90KHhfZGVuc2l0eV9wbG90LCBwbG90bHlfZW1wdHkoKSwgcG9pbnRfcGxvdCwgeV9kZW5zaXR5X3Bsb3QsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC4xNSwgMC44NSksIHdpZHRocyA9IGMoMC45LCAwLjEpLCBzaGFyZVggPSBUUlVFLCBzaGFyZVkgPSBUUlVFLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0Kc3ViMiA8LSBzdWJwbG90KHF1YWx0aWxlX3Bsb3QsIHBsb3RseV9lbXB0eSgpLCBtYXJnaW4gPSAwLCB3aWR0aHMgPSBjKDAuOSwgMC4xMCksIHRpdGxlWCA9IEZBTFNFLCB0aXRsZVkgPSBGQUxTRSkgJT4lIGxheW91dCgpDQpmaWcgPC0gc3VicGxvdChzdWIxLCBzdWIyLCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuOCwgMC4yKSwgc2hhcmVYID0gVFJVRSkgJT4lIGxheW91dCh4YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lWzFdKSwgeWF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsyXSkpDQogIA0KZmlnDQpgYGANCg0KLS0tDQptdWx0aXZhcmlhdGUgcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycyArIGZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlDQotLS0NCndpdGggYSBiaWdnZXIgcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycyBjb21lcyByZWxhdGl2ZWx5IGxpbmVhcmx5IGEgYmlnZ2VyIGZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlLCBidXQgbW9zdCBwcm9kdWNlciBoYXZlIGEgc21hbGxlciAzIA0KDQpgYGB7cn0NCiMgdHdvIHZhcmlhYmxlcywgY29udGludW91cyB4LCBjb250aW51b3VzIHksIHNob3cgdHJlbmQgYW5kIGRpc3RyaWJ1dGlvbg0KbmFtZSA9IGMoJ3Byb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMnLCAnZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUnKQ0KZGYgPC0gcGxhc3RpYyAlPiUgcmVuYW1lKHggPSBwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzLCB5ID0gZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUpICU+JSBzZWxlY3QoeCwgeSkgDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fc21vb3RoLmh0bWwNCnBvaW50X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgICMgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjUsIHNpemUgPSAxKSArDQogICAgZ2VvbV9ydWcoYWxwaGEgPSAwLjUpICsgIyB0d28gMWQgbWFyZ2luYWwgZGlzdHJpYnV0aW9ucywgZGlzcGxheSBpbmRpdmlkdWFsIGNhc2VzIHNvIGFyZSBiZXN0IHVzZWQgd2l0aCBzbWFsbGVyIGRhdGFzZXRzDQogICAgZ2VvbV9kZW5zaXR5XzJkKGFscGhhID0gMC4yLCBiaW5zID0gNCkgKyMgMkQga2VybmVsIGRlbnNpdHkgZXN0aW1hdGlvbiB1c2luZyBNQVNTOjprZGUyZCgpIGFuZCBkaXNwbGF5IHRoZSByZXN1bHRzIHdpdGggY29udG91cnMNCiAgICBnZW9tX3Ntb290aChmaWxsID0gImdyZXk5MCIpICsgIyBhaWRzIHRoZSBleWUgaW4gc2VlaW5nIHBhdHRlcm5zIGluIHRoZSBwcmVzZW5jZSBvZiBvdmVycGxvdHRpbmcNCiAgICBnZW9tX3BvaW50KGFscGhhID0gMC43NSkgKyAjIHBvaW50IGdlb20gaXMgdXNlZCB0byBjcmVhdGUgc2NhdHRlcnBsb3RzDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJ0cmVuZCBvZiIsIG5hbWVbMl0sICJvdmVyIiwgbmFtZVsxXSwgc2VwPSIgIikpIA0KcG9pbnRfcGxvdCA8LSBnZ3Bsb3RseShwb2ludF9wbG90KSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFKSkNCg0KeF9kZW5zaXR5X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgpKSArDQogICAgc3RhdF9kZW5zaXR5KGdlb209ImxpbmUiKSArICMgZHJhd3Mga2VybmVsIGRlbnNpdHkgZXN0aW1hdGUsIHdoaWNoIGlzIGEgc21vb3RoZWQgdmVyc2lvbiBvZiB0aGUgaGlzdG9ncmFtDQogICAgIyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQp4X2RlbnNpdHlfcGxvdCA8LSBnZ3Bsb3RseSh4X2RlbnNpdHlfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KeV9kZW5zaXR5X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHkpKSArDQogICAgc3RhdF9kZW5zaXR5KGdlb209ImxpbmUiKSArICMgZHJhd3Mga2VybmVsIGRlbnNpdHkgZXN0aW1hdGUsIHdoaWNoIGlzIGEgc21vb3RoZWQgdmVyc2lvbiBvZiB0aGUgaGlzdG9ncmFtDQogICAgIyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnlfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHlfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3F1YW50aWxlLmh0bWwNCnF1YWx0aWxlX3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgIGdlb21fcXVhbnRpbGUoYWxwaGEgPSAwLjgpICsgIyBmaXRzIGEgcXVhbnRpbGUgcmVncmVzc2lvbiB0byB0aGUgZGF0YSBhbmQgZHJhd3MgdGhlIGZpdHRlZCBxdWFudGlsZXMgd2l0aCBsaW5lcw0KICAgIHRoZW1lX21pbmltYWwoKSANCnF1YWx0aWxlX3Bsb3QgPC0gZ2dwbG90bHkocXVhbHRpbGVfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgbWVyZ2UgZmlndXJlcyBpbnRvIG9uZSBwbG90LCB2aWEgc3VicGxvdHMsIGh0dHBzOi8vcGxvdGx5LXIuY29tL2FycmFuZ2luZy12aWV3cy5odG1sDQpzdWIxIDwtIHN1YnBsb3QoeF9kZW5zaXR5X3Bsb3QsIHBsb3RseV9lbXB0eSgpLCBwb2ludF9wbG90LCB5X2RlbnNpdHlfcGxvdCwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjE1LCAwLjg1KSwgd2lkdGhzID0gYygwLjksIDAuMSksIHNoYXJlWCA9IFRSVUUsIHNoYXJlWSA9IFRSVUUsIHRpdGxlWCA9IEZBTFNFLCB0aXRsZVkgPSBGQUxTRSkgJT4lIGxheW91dCgpDQpzdWIyIDwtIHN1YnBsb3QocXVhbHRpbGVfcGxvdCwgcGxvdGx5X2VtcHR5KCksIG1hcmdpbiA9IDAsIHdpZHRocyA9IGMoMC45LCAwLjEwKSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCmZpZyA8LSBzdWJwbG90KHN1YjEsIHN1YjIsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC44LCAwLjIpLCBzaGFyZVggPSBUUlVFKSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMV0pLCB5YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lWzJdKSkNCiAgDQpmaWcNCmBgYA0KDQotLS0NCm11bHRpdmFyaWF0ZSBwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzICsgcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUNCi0tLQ0KcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb3ZlciBwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzIHNob3dzIGFnYWluIHRoZSBjYXAgaW4gcmlnaWRfZm9ybWF0IHBhcnQgbm90IGdyb3dpbmcgYmV5b25kIDEuMyB3aXRoIHByb2R1Y3Rpb24sIGJ1dCBhbHNvIGEgc2Vjb25kIHRlbmRlbmN5IGluIHRoZSBiZWdpbm5pbmcgd2hlcmUgYSBsaW5lYXIgYmVoYXZpb3Igb2Ygc3Ryb25nIGdyb3dpbmcgcmlnaWRfZm9ybWF0IHN1Z2dlc3QgdGhhdCB0aGVyZSBtaWdodCBiZSB0d28gc3ViLXBvcHVsYXRpb25zDQoNCmBgYHtyfQ0KIyB0d28gdmFyaWFibGVzLCBjb250aW51b3VzIHgsIGNvbnRpbnVvdXMgeSwgc2hvdyB0cmVuZCBhbmQgZGlzdHJpYnV0aW9uDQpuYW1lID0gYygncHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycycsICdyaWdpZF9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZScpDQpkZiA8LSBwbGFzdGljICU+JSByZW5hbWUoeCA9IHByb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMsIHkgPSByaWdpZF9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSkgJT4lIHNlbGVjdCh4LCB5KSANCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9zbW9vdGguaHRtbA0KcG9pbnRfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgIyBnZW9tX2ppdHRlcihhbHBoYSA9IDAuNSwgc2l6ZSA9IDEpICsNCiAgICBnZW9tX3J1ZyhhbHBoYSA9IDAuNSkgKyAjIHR3byAxZCBtYXJnaW5hbCBkaXN0cmlidXRpb25zLCBkaXNwbGF5IGluZGl2aWR1YWwgY2FzZXMgc28gYXJlIGJlc3QgdXNlZCB3aXRoIHNtYWxsZXIgZGF0YXNldHMNCiAgICBnZW9tX2RlbnNpdHlfMmQoYWxwaGEgPSAwLjIsIGJpbnMgPSA0KSArIyAyRCBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uIHVzaW5nIE1BU1M6OmtkZTJkKCkgYW5kIGRpc3BsYXkgdGhlIHJlc3VsdHMgd2l0aCBjb250b3Vycw0KICAgIGdlb21fc21vb3RoKGZpbGwgPSAiZ3JleTkwIikgKyAjIGFpZHMgdGhlIGV5ZSBpbiBzZWVpbmcgcGF0dGVybnMgaW4gdGhlIHByZXNlbmNlIG9mIG92ZXJwbG90dGluZw0KICAgIGdlb21fcG9pbnQoYWxwaGEgPSAwLjc1KSArICMgcG9pbnQgZ2VvbSBpcyB1c2VkIHRvIGNyZWF0ZSBzY2F0dGVycGxvdHMNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUocGFzdGUoInRyZW5kIG9mIiwgbmFtZVsyXSwgIm92ZXIiLCBuYW1lWzFdLCBzZXA9IiAiKSkgDQpwb2ludF9wbG90IDwtIGdncGxvdGx5KHBvaW50X3Bsb3QpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UpKQ0KDQp4X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnhfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHhfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQp5X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geSkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeV9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeV9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXVhbnRpbGUuaHRtbA0KcXVhbHRpbGVfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgZ2VvbV9xdWFudGlsZShhbHBoYSA9IDAuOCkgKyAjIGZpdHMgYSBxdWFudGlsZSByZWdyZXNzaW9uIHRvIHRoZSBkYXRhIGFuZCBkcmF3cyB0aGUgZml0dGVkIHF1YW50aWxlcyB3aXRoIGxpbmVzDQogICAgdGhlbWVfbWluaW1hbCgpIA0KcXVhbHRpbGVfcGxvdCA8LSBnZ3Bsb3RseShxdWFsdGlsZV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBtZXJnZSBmaWd1cmVzIGludG8gb25lIHBsb3QsIHZpYSBzdWJwbG90cywgaHR0cHM6Ly9wbG90bHktci5jb20vYXJyYW5naW5nLXZpZXdzLmh0bWwNCnN1YjEgPC0gc3VicGxvdCh4X2RlbnNpdHlfcGxvdCwgcGxvdGx5X2VtcHR5KCksIHBvaW50X3Bsb3QsIHlfZGVuc2l0eV9wbG90LCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuMTUsIDAuODUpLCB3aWR0aHMgPSBjKDAuOSwgMC4xKSwgc2hhcmVYID0gVFJVRSwgc2hhcmVZID0gVFJVRSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCnN1YjIgPC0gc3VicGxvdChxdWFsdGlsZV9wbG90LCBwbG90bHlfZW1wdHkoKSwgbWFyZ2luID0gMCwgd2lkdGhzID0gYygwLjksIDAuMTApLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0KZmlnIDwtIHN1YnBsb3Qoc3ViMSwgc3ViMiwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjgsIDAuMiksIHNoYXJlWCA9IFRSVUUpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsxXSksIHlheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMl0pKQ0KICANCmZpZw0KYGBgDQoNCi0tLQ0KbXVsdGl2YXJpYXRlIHByb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMgKyB0b3RhbF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlDQotLS0NCnRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb3ZlciBwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzIGxvb2tzIHByZXR0eSBtdWNoIGxpbmVhciwgd2l0aCBhIGJ1bGsgb2YgZGF0YSBwb2ludHMgYmVsb3cgcHJvZHVjdGlvbiA8IDMNCg0KYGBge3J9DQojIHR3byB2YXJpYWJsZXMsIGNvbnRpbnVvdXMgeCwgY29udGludW91cyB5LCBzaG93IHRyZW5kIGFuZCBkaXN0cmlidXRpb24NCm5hbWUgPSBjKCdwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzJywgJ3RvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUnKQ0KZGYgPC0gcGxhc3RpYyAlPiUgcmVuYW1lKHggPSBwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzLCB5ID0gdG90YWxfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSkgJT4lIHNlbGVjdCh4LCB5KSANCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9zbW9vdGguaHRtbA0KcG9pbnRfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgIyBnZW9tX2ppdHRlcihhbHBoYSA9IDAuNSwgc2l6ZSA9IDEpICsNCiAgICBnZW9tX3J1ZyhhbHBoYSA9IDAuNSkgKyAjIHR3byAxZCBtYXJnaW5hbCBkaXN0cmlidXRpb25zLCBkaXNwbGF5IGluZGl2aWR1YWwgY2FzZXMgc28gYXJlIGJlc3QgdXNlZCB3aXRoIHNtYWxsZXIgZGF0YXNldHMNCiAgICBnZW9tX2RlbnNpdHlfMmQoYWxwaGEgPSAwLjIsIGJpbnMgPSA0KSArIyAyRCBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uIHVzaW5nIE1BU1M6OmtkZTJkKCkgYW5kIGRpc3BsYXkgdGhlIHJlc3VsdHMgd2l0aCBjb250b3Vycw0KICAgIGdlb21fc21vb3RoKGZpbGwgPSAiZ3JleTkwIikgKyAjIGFpZHMgdGhlIGV5ZSBpbiBzZWVpbmcgcGF0dGVybnMgaW4gdGhlIHByZXNlbmNlIG9mIG92ZXJwbG90dGluZw0KICAgIGdlb21fcG9pbnQoYWxwaGEgPSAwLjc1KSArICMgcG9pbnQgZ2VvbSBpcyB1c2VkIHRvIGNyZWF0ZSBzY2F0dGVycGxvdHMNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUocGFzdGUoInRyZW5kIG9mIiwgbmFtZVsyXSwgIm92ZXIiLCBuYW1lWzFdLCBzZXA9IiAiKSkgDQpwb2ludF9wbG90IDwtIGdncGxvdGx5KHBvaW50X3Bsb3QpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UpKQ0KDQp4X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnhfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHhfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQp5X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geSkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeV9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeV9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXVhbnRpbGUuaHRtbA0KcXVhbHRpbGVfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgZ2VvbV9xdWFudGlsZShhbHBoYSA9IDAuOCkgKyAjIGZpdHMgYSBxdWFudGlsZSByZWdyZXNzaW9uIHRvIHRoZSBkYXRhIGFuZCBkcmF3cyB0aGUgZml0dGVkIHF1YW50aWxlcyB3aXRoIGxpbmVzDQogICAgdGhlbWVfbWluaW1hbCgpIA0KcXVhbHRpbGVfcGxvdCA8LSBnZ3Bsb3RseShxdWFsdGlsZV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBtZXJnZSBmaWd1cmVzIGludG8gb25lIHBsb3QsIHZpYSBzdWJwbG90cywgaHR0cHM6Ly9wbG90bHktci5jb20vYXJyYW5naW5nLXZpZXdzLmh0bWwNCnN1YjEgPC0gc3VicGxvdCh4X2RlbnNpdHlfcGxvdCwgcGxvdGx5X2VtcHR5KCksIHBvaW50X3Bsb3QsIHlfZGVuc2l0eV9wbG90LCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuMTUsIDAuODUpLCB3aWR0aHMgPSBjKDAuOSwgMC4xKSwgc2hhcmVYID0gVFJVRSwgc2hhcmVZID0gVFJVRSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCnN1YjIgPC0gc3VicGxvdChxdWFsdGlsZV9wbG90LCBwbG90bHlfZW1wdHkoKSwgbWFyZ2luID0gMCwgd2lkdGhzID0gYygwLjksIDAuMTApLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0KZmlnIDwtIHN1YnBsb3Qoc3ViMSwgc3ViMiwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjgsIDAuMiksIHNoYXJlWCA9IFRSVUUpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsxXSksIHlheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMl0pKQ0KICANCmZpZw0KYGBgDQoNCi0tLQ0KbXVsdGl2YXJpYXRlIHByb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMgKyB0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbg0KLS0tDQppbiB0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbiBvdmVyIHByb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMgYmVsb3cgcHJvZHVjdGlvbiA8IDMgdGhlcmUgYXJlIHR3byBjbHVzdGVyIGFyb3VuZCAwLjQ1IGFuZCAxLjAsIGJleW9uZCBwcm9kdWN0aW9uID4gMyBpdCBzZWVtcyB0byBiZSBzdGFibGUgYXQgMC41DQoNCmBgYHtyfQ0KIyB0d28gdmFyaWFibGVzLCBjb250aW51b3VzIHgsIGNvbnRpbnVvdXMgeSwgc2hvdyB0cmVuZCBhbmQgZGlzdHJpYnV0aW9uDQpuYW1lID0gYygncHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycycsICd0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbicpDQpkZiA8LSBwbGFzdGljICU+JSByZW5hbWUoeCA9IHByb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMsIHkgPSB0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbikgJT4lIHNlbGVjdCh4LCB5KSANCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9zbW9vdGguaHRtbA0KcG9pbnRfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgIyBnZW9tX2ppdHRlcihhbHBoYSA9IDAuNSwgc2l6ZSA9IDEpICsNCiAgICBnZW9tX3J1ZyhhbHBoYSA9IDAuNSkgKyAjIHR3byAxZCBtYXJnaW5hbCBkaXN0cmlidXRpb25zLCBkaXNwbGF5IGluZGl2aWR1YWwgY2FzZXMgc28gYXJlIGJlc3QgdXNlZCB3aXRoIHNtYWxsZXIgZGF0YXNldHMNCiAgICBnZW9tX2RlbnNpdHlfMmQoYWxwaGEgPSAwLjIsIGJpbnMgPSA0KSArIyAyRCBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uIHVzaW5nIE1BU1M6OmtkZTJkKCkgYW5kIGRpc3BsYXkgdGhlIHJlc3VsdHMgd2l0aCBjb250b3Vycw0KICAgIGdlb21fc21vb3RoKGZpbGwgPSAiZ3JleTkwIikgKyAjIGFpZHMgdGhlIGV5ZSBpbiBzZWVpbmcgcGF0dGVybnMgaW4gdGhlIHByZXNlbmNlIG9mIG92ZXJwbG90dGluZw0KICAgIGdlb21fcG9pbnQoYWxwaGEgPSAwLjc1KSArICMgcG9pbnQgZ2VvbSBpcyB1c2VkIHRvIGNyZWF0ZSBzY2F0dGVycGxvdHMNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUocGFzdGUoInRyZW5kIG9mIiwgbmFtZVsyXSwgIm92ZXIiLCBuYW1lWzFdLCBzZXA9IiAiKSkgDQpwb2ludF9wbG90IDwtIGdncGxvdGx5KHBvaW50X3Bsb3QpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UpKQ0KDQp4X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnhfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHhfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQp5X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geSkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeV9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeV9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXVhbnRpbGUuaHRtbA0KcXVhbHRpbGVfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgZ2VvbV9xdWFudGlsZShhbHBoYSA9IDAuOCkgKyAjIGZpdHMgYSBxdWFudGlsZSByZWdyZXNzaW9uIHRvIHRoZSBkYXRhIGFuZCBkcmF3cyB0aGUgZml0dGVkIHF1YW50aWxlcyB3aXRoIGxpbmVzDQogICAgdGhlbWVfbWluaW1hbCgpIA0KcXVhbHRpbGVfcGxvdCA8LSBnZ3Bsb3RseShxdWFsdGlsZV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBtZXJnZSBmaWd1cmVzIGludG8gb25lIHBsb3QsIHZpYSBzdWJwbG90cywgaHR0cHM6Ly9wbG90bHktci5jb20vYXJyYW5naW5nLXZpZXdzLmh0bWwNCnN1YjEgPC0gc3VicGxvdCh4X2RlbnNpdHlfcGxvdCwgcGxvdGx5X2VtcHR5KCksIHBvaW50X3Bsb3QsIHlfZGVuc2l0eV9wbG90LCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuMTUsIDAuODUpLCB3aWR0aHMgPSBjKDAuOSwgMC4xKSwgc2hhcmVYID0gVFJVRSwgc2hhcmVZID0gVFJVRSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCnN1YjIgPC0gc3VicGxvdChxdWFsdGlsZV9wbG90LCBwbG90bHlfZW1wdHkoKSwgbWFyZ2luID0gMCwgd2lkdGhzID0gYygwLjksIDAuMTApLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0KZmlnIDwtIHN1YnBsb3Qoc3ViMSwgc3ViMiwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjgsIDAuMiksIHNoYXJlWCA9IFRSVUUpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsxXSksIHlheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMl0pKQ0KICANCmZpZw0KYGBgDQoNCi0tLQ0KbXVsdGl2YXJpYXRlIGZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlICsgcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUNCi0tLQ0KcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb3ZlciBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBzaG93cyB0aGUgcHJldmlvdXNseSBvYnNlcnZlZCBwaMOkbm9tZW5hLCBpKSB3aXRoIGdyb3dpbmcgZmxleGlibGVfZm9ybWF0LCByaWdpZF9mb3JtYXQgYWxzbyBzdGFydCB0byBncm93IGEgbGl0dGxlIGJ1dCB0aGVuIHN0YXlzIGF0IGFyb3VuZCAxLjIsIGlpKSB0aGVyZSBpcyBvbmUgZ3JvdXAgdGhhdCBvbmx5IGdyb3dzIGluIHJpZ2lkX2Zvcm1hdCBhbmQgcHJvZHVjZSBhbG1vc3Qgbm8gZmxleGlibGVfZm9ybWF0DQoNCmBgYHtyfQ0KIyB0d28gdmFyaWFibGVzLCBjb250aW51b3VzIHgsIGNvbnRpbnVvdXMgeSwgc2hvdyB0cmVuZCBhbmQgZGlzdHJpYnV0aW9uDQpuYW1lID0gYygnZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUnLCAncmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUnKQ0KZGYgPC0gcGxhc3RpYyAlPiUgcmVuYW1lKHggPSBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSwgeSA9IHJpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlKSAlPiUgc2VsZWN0KHgsIHkpIA0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3Ntb290aC5odG1sDQpwb2ludF9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICAjIGdlb21faml0dGVyKGFscGhhID0gMC41LCBzaXplID0gMSkgKw0KICAgIGdlb21fcnVnKGFscGhhID0gMC41KSArICMgdHdvIDFkIG1hcmdpbmFsIGRpc3RyaWJ1dGlvbnMsIGRpc3BsYXkgaW5kaXZpZHVhbCBjYXNlcyBzbyBhcmUgYmVzdCB1c2VkIHdpdGggc21hbGxlciBkYXRhc2V0cw0KICAgIGdlb21fZGVuc2l0eV8yZChhbHBoYSA9IDAuMiwgYmlucyA9IDQpICsjIDJEIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRpb24gdXNpbmcgTUFTUzo6a2RlMmQoKSBhbmQgZGlzcGxheSB0aGUgcmVzdWx0cyB3aXRoIGNvbnRvdXJzDQogICAgZ2VvbV9zbW9vdGgoZmlsbCA9ICJncmV5OTAiKSArICMgYWlkcyB0aGUgZXllIGluIHNlZWluZyBwYXR0ZXJucyBpbiB0aGUgcHJlc2VuY2Ugb2Ygb3ZlcnBsb3R0aW5nDQogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNzUpICsgIyBwb2ludCBnZW9tIGlzIHVzZWQgdG8gY3JlYXRlIHNjYXR0ZXJwbG90cw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgZ2d0aXRsZShwYXN0ZSgidHJlbmQgb2YiLCBuYW1lWzJdLCAib3ZlciIsIG5hbWVbMV0sIHNlcD0iICIpKSANCnBvaW50X3Bsb3QgPC0gZ2dwbG90bHkocG9pbnRfcGxvdCkgJT4lIGxheW91dCh4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSkpDQoNCnhfZGVuc2l0eV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4KSkgKw0KICAgIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIikgKyAjIGRyYXdzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlLCB3aGljaCBpcyBhIHNtb290aGVkIHZlcnNpb24gb2YgdGhlIGhpc3RvZ3JhbQ0KICAgICMgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeF9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeF9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCnlfZGVuc2l0eV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5KSkgKw0KICAgIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIikgKyAjIGRyYXdzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlLCB3aGljaCBpcyBhIHNtb290aGVkIHZlcnNpb24gb2YgdGhlIGhpc3RvZ3JhbQ0KICAgICMgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQp5X2RlbnNpdHlfcGxvdCA8LSBnZ3Bsb3RseSh5X2RlbnNpdHlfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9xdWFudGlsZS5odG1sDQpxdWFsdGlsZV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICBnZW9tX3F1YW50aWxlKGFscGhhID0gMC44KSArICMgZml0cyBhIHF1YW50aWxlIHJlZ3Jlc3Npb24gdG8gdGhlIGRhdGEgYW5kIGRyYXdzIHRoZSBmaXR0ZWQgcXVhbnRpbGVzIHdpdGggbGluZXMNCiAgICB0aGVtZV9taW5pbWFsKCkgDQpxdWFsdGlsZV9wbG90IDwtIGdncGxvdGx5KHF1YWx0aWxlX3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIG1lcmdlIGZpZ3VyZXMgaW50byBvbmUgcGxvdCwgdmlhIHN1YnBsb3RzLCBodHRwczovL3Bsb3RseS1yLmNvbS9hcnJhbmdpbmctdmlld3MuaHRtbA0Kc3ViMSA8LSBzdWJwbG90KHhfZGVuc2l0eV9wbG90LCBwbG90bHlfZW1wdHkoKSwgcG9pbnRfcGxvdCwgeV9kZW5zaXR5X3Bsb3QsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC4xNSwgMC44NSksIHdpZHRocyA9IGMoMC45LCAwLjEpLCBzaGFyZVggPSBUUlVFLCBzaGFyZVkgPSBUUlVFLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0Kc3ViMiA8LSBzdWJwbG90KHF1YWx0aWxlX3Bsb3QsIHBsb3RseV9lbXB0eSgpLCBtYXJnaW4gPSAwLCB3aWR0aHMgPSBjKDAuOSwgMC4xMCksIHRpdGxlWCA9IEZBTFNFLCB0aXRsZVkgPSBGQUxTRSkgJT4lIGxheW91dCgpDQpmaWcgPC0gc3VicGxvdChzdWIxLCBzdWIyLCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuOCwgMC4yKSwgc2hhcmVYID0gVFJVRSkgJT4lIGxheW91dCh4YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lWzFdKSwgeWF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsyXSkpDQogIA0KZmlnDQpgYGANCg0KLS0tDQptdWx0aXZhcmlhdGUgZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgKyB0b3RhbF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlDQotLS0NCmZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlIG92ZXIgdG90YWxfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBzaG93cyBhbiBhbG1vc3QgbGluZWFyIGluY3JlYXNlIGluIGZsZXhpYmxlX2Zvcm1hdCB3aXRoIHRvdGFsX2NvbnRyaWJ1dGlvbiwgYnV0IGhlcmUgYWdhaW4gd2UgaGF2ZSBhIGdyb3VwIHdpdGggYWxtb3N0IG5vIGZsZXhpYmxlX2Zvcm1hdCAod2hpY2ggbWVhbnMgdGhhdCB0aGV5IG9ubHkgcHJvZHVjZSByaWdpZF9mb3JtYXQpDQoNCmBgYHtyfQ0KIyB0d28gdmFyaWFibGVzLCBjb250aW51b3VzIHgsIGNvbnRpbnVvdXMgeSwgc2hvdyB0cmVuZCBhbmQgZGlzdHJpYnV0aW9uDQpuYW1lID0gYygndG90YWxfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZScsICdmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZScpDQpkZiA8LSBwbGFzdGljICU+JSByZW5hbWUoeCA9IHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUsIHkgPSBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSkgJT4lIHNlbGVjdCh4LCB5KSANCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9zbW9vdGguaHRtbA0KcG9pbnRfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgIyBnZW9tX2ppdHRlcihhbHBoYSA9IDAuNSwgc2l6ZSA9IDEpICsNCiAgICBnZW9tX3J1ZyhhbHBoYSA9IDAuNSkgKyAjIHR3byAxZCBtYXJnaW5hbCBkaXN0cmlidXRpb25zLCBkaXNwbGF5IGluZGl2aWR1YWwgY2FzZXMgc28gYXJlIGJlc3QgdXNlZCB3aXRoIHNtYWxsZXIgZGF0YXNldHMNCiAgICBnZW9tX2RlbnNpdHlfMmQoYWxwaGEgPSAwLjIsIGJpbnMgPSA0KSArIyAyRCBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uIHVzaW5nIE1BU1M6OmtkZTJkKCkgYW5kIGRpc3BsYXkgdGhlIHJlc3VsdHMgd2l0aCBjb250b3Vycw0KICAgIGdlb21fc21vb3RoKGZpbGwgPSAiZ3JleTkwIikgKyAjIGFpZHMgdGhlIGV5ZSBpbiBzZWVpbmcgcGF0dGVybnMgaW4gdGhlIHByZXNlbmNlIG9mIG92ZXJwbG90dGluZw0KICAgIGdlb21fcG9pbnQoYWxwaGEgPSAwLjc1KSArICMgcG9pbnQgZ2VvbSBpcyB1c2VkIHRvIGNyZWF0ZSBzY2F0dGVycGxvdHMNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUocGFzdGUoInRyZW5kIG9mIiwgbmFtZVsyXSwgIm92ZXIiLCBuYW1lWzFdLCBzZXA9IiAiKSkgDQpwb2ludF9wbG90IDwtIGdncGxvdGx5KHBvaW50X3Bsb3QpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UpKQ0KDQp4X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnhfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHhfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQp5X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geSkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeV9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeV9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXVhbnRpbGUuaHRtbA0KcXVhbHRpbGVfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgZ2VvbV9xdWFudGlsZShhbHBoYSA9IDAuOCkgKyAjIGZpdHMgYSBxdWFudGlsZSByZWdyZXNzaW9uIHRvIHRoZSBkYXRhIGFuZCBkcmF3cyB0aGUgZml0dGVkIHF1YW50aWxlcyB3aXRoIGxpbmVzDQogICAgdGhlbWVfbWluaW1hbCgpIA0KcXVhbHRpbGVfcGxvdCA8LSBnZ3Bsb3RseShxdWFsdGlsZV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBtZXJnZSBmaWd1cmVzIGludG8gb25lIHBsb3QsIHZpYSBzdWJwbG90cywgaHR0cHM6Ly9wbG90bHktci5jb20vYXJyYW5naW5nLXZpZXdzLmh0bWwNCnN1YjEgPC0gc3VicGxvdCh4X2RlbnNpdHlfcGxvdCwgcGxvdGx5X2VtcHR5KCksIHBvaW50X3Bsb3QsIHlfZGVuc2l0eV9wbG90LCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuMTUsIDAuODUpLCB3aWR0aHMgPSBjKDAuOSwgMC4xKSwgc2hhcmVYID0gVFJVRSwgc2hhcmVZID0gVFJVRSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCnN1YjIgPC0gc3VicGxvdChxdWFsdGlsZV9wbG90LCBwbG90bHlfZW1wdHkoKSwgbWFyZ2luID0gMCwgd2lkdGhzID0gYygwLjksIDAuMTApLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0KZmlnIDwtIHN1YnBsb3Qoc3ViMSwgc3ViMiwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjgsIDAuMiksIHNoYXJlWCA9IFRSVUUpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsxXSksIHlheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMl0pKQ0KICANCmZpZw0KYGBgDQoNCi0tLQ0KbXVsdGl2YXJpYXRlIGZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlICsgdG90YWxfd2FzdGVfZGl2X3Byb2R1Y3Rpb24NCi0tLQ0KdG90YWxfd2FzdGVfZGl2X3Byb2R1Y3Rpb24gb3ZlciBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBzaG93cyBhZ2FuaSB0cXdvIGNsdXN0ZXJzIG9uZSBhcm91bmQgdG90YWxfd2FzdGVfZGl2IDEuMCBhbmQgdGhlIG90aGVyIGFyb3VuZCAwLjQ1LCBhbmQgdGhhdCB0aGUgaGlnaGVyIHJlZ2lvbnMgb2YgZmxleGlibGVfZm9ybWF0IGFyZSBvbmx5IG92dnVwaWVkIGJ5IGEgZmV3IHByb2R1Y2VycyB3aXRoIGEgcmF0aW9uIGFyb3VuZCAwLjQ3IA0KDQpgYGB7cn0NCiMgdHdvIHZhcmlhYmxlcywgY29udGludW91cyB4LCBjb250aW51b3VzIHksIHNob3cgdHJlbmQgYW5kIGRpc3RyaWJ1dGlvbg0KbmFtZSA9IGMoJ2ZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlJywgJ3RvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uJykNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh4ID0gZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUsIHkgPSB0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbikgJT4lIHNlbGVjdCh4LCB5KSANCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9zbW9vdGguaHRtbA0KcG9pbnRfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgIyBnZW9tX2ppdHRlcihhbHBoYSA9IDAuNSwgc2l6ZSA9IDEpICsNCiAgICBnZW9tX3J1ZyhhbHBoYSA9IDAuNSkgKyAjIHR3byAxZCBtYXJnaW5hbCBkaXN0cmlidXRpb25zLCBkaXNwbGF5IGluZGl2aWR1YWwgY2FzZXMgc28gYXJlIGJlc3QgdXNlZCB3aXRoIHNtYWxsZXIgZGF0YXNldHMNCiAgICBnZW9tX2RlbnNpdHlfMmQoYWxwaGEgPSAwLjIsIGJpbnMgPSA0KSArIyAyRCBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uIHVzaW5nIE1BU1M6OmtkZTJkKCkgYW5kIGRpc3BsYXkgdGhlIHJlc3VsdHMgd2l0aCBjb250b3Vycw0KICAgIGdlb21fc21vb3RoKGZpbGwgPSAiZ3JleTkwIikgKyAjIGFpZHMgdGhlIGV5ZSBpbiBzZWVpbmcgcGF0dGVybnMgaW4gdGhlIHByZXNlbmNlIG9mIG92ZXJwbG90dGluZw0KICAgIGdlb21fcG9pbnQoYWxwaGEgPSAwLjc1KSArICMgcG9pbnQgZ2VvbSBpcyB1c2VkIHRvIGNyZWF0ZSBzY2F0dGVycGxvdHMNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUocGFzdGUoInRyZW5kIG9mIiwgbmFtZVsyXSwgIm92ZXIiLCBuYW1lWzFdLCBzZXA9IiAiKSkgDQpwb2ludF9wbG90IDwtIGdncGxvdGx5KHBvaW50X3Bsb3QpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UpKQ0KDQp4X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnhfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHhfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQp5X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geSkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeV9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeV9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXVhbnRpbGUuaHRtbA0KcXVhbHRpbGVfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgZ2VvbV9xdWFudGlsZShhbHBoYSA9IDAuOCkgKyAjIGZpdHMgYSBxdWFudGlsZSByZWdyZXNzaW9uIHRvIHRoZSBkYXRhIGFuZCBkcmF3cyB0aGUgZml0dGVkIHF1YW50aWxlcyB3aXRoIGxpbmVzDQogICAgdGhlbWVfbWluaW1hbCgpIA0KcXVhbHRpbGVfcGxvdCA8LSBnZ3Bsb3RseShxdWFsdGlsZV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBtZXJnZSBmaWd1cmVzIGludG8gb25lIHBsb3QsIHZpYSBzdWJwbG90cywgaHR0cHM6Ly9wbG90bHktci5jb20vYXJyYW5naW5nLXZpZXdzLmh0bWwNCnN1YjEgPC0gc3VicGxvdCh4X2RlbnNpdHlfcGxvdCwgcGxvdGx5X2VtcHR5KCksIHBvaW50X3Bsb3QsIHlfZGVuc2l0eV9wbG90LCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuMTUsIDAuODUpLCB3aWR0aHMgPSBjKDAuOSwgMC4xKSwgc2hhcmVYID0gVFJVRSwgc2hhcmVZID0gVFJVRSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCnN1YjIgPC0gc3VicGxvdChxdWFsdGlsZV9wbG90LCBwbG90bHlfZW1wdHkoKSwgbWFyZ2luID0gMCwgd2lkdGhzID0gYygwLjksIDAuMTApLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0KZmlnIDwtIHN1YnBsb3Qoc3ViMSwgc3ViMiwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjgsIDAuMiksIHNoYXJlWCA9IFRSVUUpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsxXSksIHlheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMl0pKQ0KICANCmZpZw0KYGBgDQoNCi0tLQ0KbXVsdGl2YXJpYXRlIHJpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlICsgdG90YWxfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZQ0KLS0tDQpyaWdpZF9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBvdmVyIHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb25seSBhdCB0aGUgYmVnaW5uaW5nIHJpZ2lkIGZvcm1hdCBpcyBncm93aW5nIHdpdGggdG90YWxfY29udHJpYnV0aW9uLCBidXQgaXQgaXMgbm90IHJlYWxseSBncm93aW5nIGJleW9uZCAxLjMsIGZvciB0aGUgcmlnaWRfZm9ybWF0IG9ubHkgZ3JvdXAsIHRoZXJlIHRoZXJlIGlzIGEgYWxtb3N0IGxpbmVhciBncm91cA0KDQpgYGB7cn0NCiMgdHdvIHZhcmlhYmxlcywgY29udGludW91cyB4LCBjb250aW51b3VzIHksIHNob3cgdHJlbmQgYW5kIGRpc3RyaWJ1dGlvbg0KbmFtZSA9IGMoJ3RvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUnLCAncmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUnKQ0KZGYgPC0gcGxhc3RpYyAlPiUgcmVuYW1lKHggPSB0b3RhbF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlLCB5ID0gcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUpICU+JSBzZWxlY3QoeCwgeSkgDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fc21vb3RoLmh0bWwNCnBvaW50X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgICMgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjUsIHNpemUgPSAxKSArDQogICAgZ2VvbV9ydWcoYWxwaGEgPSAwLjUpICsgIyB0d28gMWQgbWFyZ2luYWwgZGlzdHJpYnV0aW9ucywgZGlzcGxheSBpbmRpdmlkdWFsIGNhc2VzIHNvIGFyZSBiZXN0IHVzZWQgd2l0aCBzbWFsbGVyIGRhdGFzZXRzDQogICAgZ2VvbV9kZW5zaXR5XzJkKGFscGhhID0gMC4yLCBiaW5zID0gNCkgKyMgMkQga2VybmVsIGRlbnNpdHkgZXN0aW1hdGlvbiB1c2luZyBNQVNTOjprZGUyZCgpIGFuZCBkaXNwbGF5IHRoZSByZXN1bHRzIHdpdGggY29udG91cnMNCiAgICBnZW9tX3Ntb290aChmaWxsID0gImdyZXk5MCIpICsgIyBhaWRzIHRoZSBleWUgaW4gc2VlaW5nIHBhdHRlcm5zIGluIHRoZSBwcmVzZW5jZSBvZiBvdmVycGxvdHRpbmcNCiAgICBnZW9tX3BvaW50KGFscGhhID0gMC43NSkgKyAjIHBvaW50IGdlb20gaXMgdXNlZCB0byBjcmVhdGUgc2NhdHRlcnBsb3RzDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJ0cmVuZCBvZiIsIG5hbWVbMl0sICJvdmVyIiwgbmFtZVsxXSwgc2VwPSIgIikpIA0KcG9pbnRfcGxvdCA8LSBnZ3Bsb3RseShwb2ludF9wbG90KSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFKSkNCg0KeF9kZW5zaXR5X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgpKSArDQogICAgc3RhdF9kZW5zaXR5KGdlb209ImxpbmUiKSArICMgZHJhd3Mga2VybmVsIGRlbnNpdHkgZXN0aW1hdGUsIHdoaWNoIGlzIGEgc21vb3RoZWQgdmVyc2lvbiBvZiB0aGUgaGlzdG9ncmFtDQogICAgIyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQp4X2RlbnNpdHlfcGxvdCA8LSBnZ3Bsb3RseSh4X2RlbnNpdHlfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KeV9kZW5zaXR5X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHkpKSArDQogICAgc3RhdF9kZW5zaXR5KGdlb209ImxpbmUiKSArICMgZHJhd3Mga2VybmVsIGRlbnNpdHkgZXN0aW1hdGUsIHdoaWNoIGlzIGEgc21vb3RoZWQgdmVyc2lvbiBvZiB0aGUgaGlzdG9ncmFtDQogICAgIyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnlfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHlfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3F1YW50aWxlLmh0bWwNCnF1YWx0aWxlX3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgIGdlb21fcXVhbnRpbGUoYWxwaGEgPSAwLjgpICsgIyBmaXRzIGEgcXVhbnRpbGUgcmVncmVzc2lvbiB0byB0aGUgZGF0YSBhbmQgZHJhd3MgdGhlIGZpdHRlZCBxdWFudGlsZXMgd2l0aCBsaW5lcw0KICAgIHRoZW1lX21pbmltYWwoKSANCnF1YWx0aWxlX3Bsb3QgPC0gZ2dwbG90bHkocXVhbHRpbGVfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgbWVyZ2UgZmlndXJlcyBpbnRvIG9uZSBwbG90LCB2aWEgc3VicGxvdHMsIGh0dHBzOi8vcGxvdGx5LXIuY29tL2FycmFuZ2luZy12aWV3cy5odG1sDQpzdWIxIDwtIHN1YnBsb3QoeF9kZW5zaXR5X3Bsb3QsIHBsb3RseV9lbXB0eSgpLCBwb2ludF9wbG90LCB5X2RlbnNpdHlfcGxvdCwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjE1LCAwLjg1KSwgd2lkdGhzID0gYygwLjksIDAuMSksIHNoYXJlWCA9IFRSVUUsIHNoYXJlWSA9IFRSVUUsIHRpdGxlWCA9IEZBTFNFLCB0aXRsZVkgPSBGQUxTRSkgJT4lIGxheW91dCgpDQpzdWIyIDwtIHN1YnBsb3QocXVhbHRpbGVfcGxvdCwgcGxvdGx5X2VtcHR5KCksIG1hcmdpbiA9IDAsIHdpZHRocyA9IGMoMC45LCAwLjEwKSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCmZpZyA8LSBzdWJwbG90KHN1YjEsIHN1YjIsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC44LCAwLjIpLCBzaGFyZVggPSBUUlVFKSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMV0pLCB5YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lWzJdKSkNCiAgDQpmaWcNCmBgYA0KDQotLS0NCm11bHRpdmFyaWF0ZSByaWdpZF9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSArIHRvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uDQotLS0NCm1vc3QgZGF0YSBwb2ludHMgbGllIGluIHRoZSByYW5nZSB0b3RhbF93YXN0ZV9kaXYgPCAwLjcgYW5kIHJpZ2lkX2Zvcm1hdCA8IDAuNSwgZm9yIHRoZSBvdXRsaWVycyB0aGVyZSBhcmUgdHdvIGdyb3VwcyBvbmUgYXJvdW5kIHJhdGlvIDEuMCBhbmQgb25lIHdpdGggbG93ZXIgcmF0aW8gYXJvdW5kIDAuNQ0KDQpgYGB7cn0NCiMgdHdvIHZhcmlhYmxlcywgY29udGludW91cyB4LCBjb250aW51b3VzIHksIHNob3cgdHJlbmQgYW5kIGRpc3RyaWJ1dGlvbg0KbmFtZSA9IGMoJ3JpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlJywgJ3RvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uJykNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh4ID0gcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUsIHkgPSB0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbikgJT4lIHNlbGVjdCh4LCB5KSANCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9zbW9vdGguaHRtbA0KcG9pbnRfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgIyBnZW9tX2ppdHRlcihhbHBoYSA9IDAuNSwgc2l6ZSA9IDEpICsNCiAgICBnZW9tX3J1ZyhhbHBoYSA9IDAuNSkgKyAjIHR3byAxZCBtYXJnaW5hbCBkaXN0cmlidXRpb25zLCBkaXNwbGF5IGluZGl2aWR1YWwgY2FzZXMgc28gYXJlIGJlc3QgdXNlZCB3aXRoIHNtYWxsZXIgZGF0YXNldHMNCiAgICBnZW9tX2RlbnNpdHlfMmQoYWxwaGEgPSAwLjIsIGJpbnMgPSA0KSArIyAyRCBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uIHVzaW5nIE1BU1M6OmtkZTJkKCkgYW5kIGRpc3BsYXkgdGhlIHJlc3VsdHMgd2l0aCBjb250b3Vycw0KICAgIGdlb21fc21vb3RoKGZpbGwgPSAiZ3JleTkwIikgKyAjIGFpZHMgdGhlIGV5ZSBpbiBzZWVpbmcgcGF0dGVybnMgaW4gdGhlIHByZXNlbmNlIG9mIG92ZXJwbG90dGluZw0KICAgIGdlb21fcG9pbnQoYWxwaGEgPSAwLjc1KSArICMgcG9pbnQgZ2VvbSBpcyB1c2VkIHRvIGNyZWF0ZSBzY2F0dGVycGxvdHMNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUocGFzdGUoInRyZW5kIG9mIiwgbmFtZVsyXSwgIm92ZXIiLCBuYW1lWzFdLCBzZXA9IiAiKSkgDQpwb2ludF9wbG90IDwtIGdncGxvdGx5KHBvaW50X3Bsb3QpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UpKQ0KDQp4X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnhfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHhfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQp5X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geSkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeV9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeV9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXVhbnRpbGUuaHRtbA0KcXVhbHRpbGVfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgZ2VvbV9xdWFudGlsZShhbHBoYSA9IDAuOCkgKyAjIGZpdHMgYSBxdWFudGlsZSByZWdyZXNzaW9uIHRvIHRoZSBkYXRhIGFuZCBkcmF3cyB0aGUgZml0dGVkIHF1YW50aWxlcyB3aXRoIGxpbmVzDQogICAgdGhlbWVfbWluaW1hbCgpIA0KcXVhbHRpbGVfcGxvdCA8LSBnZ3Bsb3RseShxdWFsdGlsZV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBtZXJnZSBmaWd1cmVzIGludG8gb25lIHBsb3QsIHZpYSBzdWJwbG90cywgaHR0cHM6Ly9wbG90bHktci5jb20vYXJyYW5naW5nLXZpZXdzLmh0bWwNCnN1YjEgPC0gc3VicGxvdCh4X2RlbnNpdHlfcGxvdCwgcGxvdGx5X2VtcHR5KCksIHBvaW50X3Bsb3QsIHlfZGVuc2l0eV9wbG90LCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuMTUsIDAuODUpLCB3aWR0aHMgPSBjKDAuOSwgMC4xKSwgc2hhcmVYID0gVFJVRSwgc2hhcmVZID0gVFJVRSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCnN1YjIgPC0gc3VicGxvdChxdWFsdGlsZV9wbG90LCBwbG90bHlfZW1wdHkoKSwgbWFyZ2luID0gMCwgd2lkdGhzID0gYygwLjksIDAuMTApLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0KZmlnIDwtIHN1YnBsb3Qoc3ViMSwgc3ViMiwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjgsIDAuMiksIHNoYXJlWCA9IFRSVUUpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsxXSksIHlheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMl0pKQ0KICANCmZpZw0KYGBgDQoNCi0tLQ0KbXVsdGl2YXJpYXRlIHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgKyB0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbg0KLS0tDQp0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbiBvdmVyIHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgc2hvd3MgYWdhaW4gdHdvIGdyb3VwcyBhcm91bmQgMS4wIGFuZCAwLjQ1IGFuZCBhIGNvbmNlbnRyYXRpb24gdW5kZXIgMC43NSB0b3RhbF9jb250cmlidXRpb24NCg0KYGBge3J9DQojIHR3byB2YXJpYWJsZXMsIGNvbnRpbnVvdXMgeCwgY29udGludW91cyB5LCBzaG93IHRyZW5kIGFuZCBkaXN0cmlidXRpb24NCm5hbWUgPSBjKCd0b3RhbF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlJywgJ3RvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uJykNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh4ID0gdG90YWxfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSwgeSA9IHRvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uKSAlPiUgc2VsZWN0KHgsIHkpIA0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3Ntb290aC5odG1sDQpwb2ludF9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICAjIGdlb21faml0dGVyKGFscGhhID0gMC41LCBzaXplID0gMSkgKw0KICAgIGdlb21fcnVnKGFscGhhID0gMC41KSArICMgdHdvIDFkIG1hcmdpbmFsIGRpc3RyaWJ1dGlvbnMsIGRpc3BsYXkgaW5kaXZpZHVhbCBjYXNlcyBzbyBhcmUgYmVzdCB1c2VkIHdpdGggc21hbGxlciBkYXRhc2V0cw0KICAgIGdlb21fZGVuc2l0eV8yZChhbHBoYSA9IDAuMiwgYmlucyA9IDQpICsjIDJEIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRpb24gdXNpbmcgTUFTUzo6a2RlMmQoKSBhbmQgZGlzcGxheSB0aGUgcmVzdWx0cyB3aXRoIGNvbnRvdXJzDQogICAgZ2VvbV9zbW9vdGgoZmlsbCA9ICJncmV5OTAiKSArICMgYWlkcyB0aGUgZXllIGluIHNlZWluZyBwYXR0ZXJucyBpbiB0aGUgcHJlc2VuY2Ugb2Ygb3ZlcnBsb3R0aW5nDQogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNzUpICsgIyBwb2ludCBnZW9tIGlzIHVzZWQgdG8gY3JlYXRlIHNjYXR0ZXJwbG90cw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgZ2d0aXRsZShwYXN0ZSgidHJlbmQgb2YiLCBuYW1lWzJdLCAib3ZlciIsIG5hbWVbMV0sIHNlcD0iICIpKSANCnBvaW50X3Bsb3QgPC0gZ2dwbG90bHkocG9pbnRfcGxvdCkgJT4lIGxheW91dCh4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSkpDQoNCnhfZGVuc2l0eV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4KSkgKw0KICAgIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIikgKyAjIGRyYXdzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlLCB3aGljaCBpcyBhIHNtb290aGVkIHZlcnNpb24gb2YgdGhlIGhpc3RvZ3JhbQ0KICAgICMgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeF9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeF9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCnlfZGVuc2l0eV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5KSkgKw0KICAgIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIikgKyAjIGRyYXdzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlLCB3aGljaCBpcyBhIHNtb290aGVkIHZlcnNpb24gb2YgdGhlIGhpc3RvZ3JhbQ0KICAgICMgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQp5X2RlbnNpdHlfcGxvdCA8LSBnZ3Bsb3RseSh5X2RlbnNpdHlfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9xdWFudGlsZS5odG1sDQpxdWFsdGlsZV9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICBnZW9tX3F1YW50aWxlKGFscGhhID0gMC44KSArICMgZml0cyBhIHF1YW50aWxlIHJlZ3Jlc3Npb24gdG8gdGhlIGRhdGEgYW5kIGRyYXdzIHRoZSBmaXR0ZWQgcXVhbnRpbGVzIHdpdGggbGluZXMNCiAgICB0aGVtZV9taW5pbWFsKCkgDQpxdWFsdGlsZV9wbG90IDwtIGdncGxvdGx5KHF1YWx0aWxlX3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIG1lcmdlIGZpZ3VyZXMgaW50byBvbmUgcGxvdCwgdmlhIHN1YnBsb3RzLCBodHRwczovL3Bsb3RseS1yLmNvbS9hcnJhbmdpbmctdmlld3MuaHRtbA0Kc3ViMSA8LSBzdWJwbG90KHhfZGVuc2l0eV9wbG90LCBwbG90bHlfZW1wdHkoKSwgcG9pbnRfcGxvdCwgeV9kZW5zaXR5X3Bsb3QsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC4xNSwgMC44NSksIHdpZHRocyA9IGMoMC45LCAwLjEpLCBzaGFyZVggPSBUUlVFLCBzaGFyZVkgPSBUUlVFLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0Kc3ViMiA8LSBzdWJwbG90KHF1YWx0aWxlX3Bsb3QsIHBsb3RseV9lbXB0eSgpLCBtYXJnaW4gPSAwLCB3aWR0aHMgPSBjKDAuOSwgMC4xMCksIHRpdGxlWCA9IEZBTFNFLCB0aXRsZVkgPSBGQUxTRSkgJT4lIGxheW91dCgpDQpmaWcgPC0gc3VicGxvdChzdWIxLCBzdWIyLCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuOCwgMC4yKSwgc2hhcmVYID0gVFJVRSkgJT4lIGxheW91dCh4YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lWzFdKSwgeWF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsyXSkpDQogIA0KZmlnDQpgYGANCg0KLS0tDQpjb21wYXJlIGZsZXhpYmxlX2Zvcm1hdCBhbmQgcmlnaWRfZm9ybWF0IG92ZXIgcHJvZHVjdGlvbg0KLS0tDQpjb21wYXJpbmcgZmxleGlibGVfZm9ybWF0IGFuZCByaWdpZF9mb3JtYXQgb3ZlciBwcm9kdWN0aW9uIHNob3dzIHVzIHRoYXQgZmxleGlibGVfZm9ybWF0IGlzIGdyb3dpbmcgbGluZWFybHkgd2hpbGUgcmlnaWQgc3RvcHMgZ3Jvd2luZyBsaW5lYXJseSBtaWQgd2F5IGF0IHByb2R1Y3Rpb24gPSA2LCBidXQgdGhpcyBncm93dGggbWlnaHQgYmUgZGlzdHVyYmVkIGJ5IHR3byBkaWZmZXJlbnQgc3ViLXBvcHVsYXRpb25zIGFuZCBpcyBleHBlY3RlZCB0byBiZSBtdWNoIGxlc3Mgc3Ryb25nIGFuZCBjYXBwaW5nIG91dCBlYXJsaWVyIA0KDQpgYGB7cn0NCiMgdGhyZWUgdmFyaWFibGVzLCBjb250aW51b3VzIHgsIHR3byBjb250aW51b3VzIHksIHNob3cgdHJlbmQgYW5kIGRpc3RyaWJ1dGlvbiANCm5hbWUgPSBjKCdwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzJywgJ3JpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlJywgJ2ZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlJykNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh4ID0gcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycywgcmlnaWQgPSByaWdpZF9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSwgZmxleGlibGUgPSBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSkgJT4lIHNlbGVjdCh4LCByaWdpZCwgZmxleGlibGUpICU+JSBwaXZvdF9sb25nZXIoY29scyA9IGMoZmxleGlibGUscmlnaWQpKSAlPiUgcmVuYW1lKHkgPSB2YWx1ZSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9zbW9vdGguaHRtbA0KcG9pbnRfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHksIGNvbG91ciA9IG5hbWUpKSArDQogICAgIyBnZW9tX2ppdHRlcihhbHBoYSA9IDAuNSwgc2l6ZSA9IDEpICsNCiAgICBnZW9tX3J1ZyhhbHBoYSA9IDAuNSkgKyAjIHR3byAxZCBtYXJnaW5hbCBkaXN0cmlidXRpb25zLCBkaXNwbGF5IGluZGl2aWR1YWwgY2FzZXMgc28gYXJlIGJlc3QgdXNlZCB3aXRoIHNtYWxsZXIgZGF0YXNldHMNCiAgICBnZW9tX2RlbnNpdHlfMmQoYWxwaGEgPSAwLjIsIGJpbnMgPSA0KSArIyAyRCBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uIHVzaW5nIE1BU1M6OmtkZTJkKCkgYW5kIGRpc3BsYXkgdGhlIHJlc3VsdHMgd2l0aCBjb250b3Vycw0KICAgIGdlb21fc21vb3RoKGZpbGwgPSAiZ3JleTkwIikgKyAjIGFpZHMgdGhlIGV5ZSBpbiBzZWVpbmcgcGF0dGVybnMgaW4gdGhlIHByZXNlbmNlIG9mIG92ZXJwbG90dGluZw0KICAgIGdlb21fcG9pbnQoYWxwaGEgPSAwLjc1KSArICMgcG9pbnQgZ2VvbSBpcyB1c2VkIHRvIGNyZWF0ZSBzY2F0dGVycGxvdHMNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUocGFzdGUoInRyZW5kIG9mIiwgbmFtZVsyXSwgIm92ZXIiLCBuYW1lWzFdLCBzZXA9IiAiKSkgDQpwb2ludF9wbG90IDwtIGdncGxvdGx5KHBvaW50X3Bsb3QpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UpKQ0KDQp4X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgY29sb3VyID0gbmFtZSkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnhfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHhfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQp5X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geSwgY29sb3VyID0gbmFtZSkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeV9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeV9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXVhbnRpbGUuaHRtbA0KcXVhbHRpbGVfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHksIGNvbG91ciA9IG5hbWUpKSArDQogICAgZ2VvbV9xdWFudGlsZShhbHBoYSA9IDAuOCkgKyAjIGZpdHMgYSBxdWFudGlsZSByZWdyZXNzaW9uIHRvIHRoZSBkYXRhIGFuZCBkcmF3cyB0aGUgZml0dGVkIHF1YW50aWxlcyB3aXRoIGxpbmVzDQogICAgdGhlbWVfbWluaW1hbCgpIA0KcXVhbHRpbGVfcGxvdCA8LSBnZ3Bsb3RseShxdWFsdGlsZV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBtZXJnZSBmaWd1cmVzIGludG8gb25lIHBsb3QsIHZpYSBzdWJwbG90cywgaHR0cHM6Ly9wbG90bHktci5jb20vYXJyYW5naW5nLXZpZXdzLmh0bWwNCnN1YjEgPC0gc3VicGxvdCh4X2RlbnNpdHlfcGxvdCwgcGxvdGx5X2VtcHR5KCksIHBvaW50X3Bsb3QsIHlfZGVuc2l0eV9wbG90LCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuMTUsIDAuODUpLCB3aWR0aHMgPSBjKDAuOSwgMC4xKSwgc2hhcmVYID0gVFJVRSwgc2hhcmVZID0gVFJVRSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkgJT4lIGhpZGVfbGVnZW5kKCkNCnN1YjIgPC0gc3VicGxvdChxdWFsdGlsZV9wbG90LCBwbG90bHlfZW1wdHkoKSwgbWFyZ2luID0gMCwgd2lkdGhzID0gYygwLjksIDAuMTApLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0KZmlnIDwtIHN1YnBsb3Qoc3ViMSwgc3ViMiwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjgsIDAuMiksIHNoYXJlWCA9IFRSVUUpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsxXSksIHlheGlzID0gbGlzdCh0aXRsZSA9IHBhc3RlKG5hbWVbMl0sICI8YnI+IiwgbmFtZVszXSwgc2VwPSIiKSkpIA0KICANCmZpZw0KYGBgDQoNCg0KDQotLS0NCmFwcGVuZGl4OiBvbGQgZXhwZXJpbWVudGFsIHBsb3RzDQotLS0NCmBgYHtyfQ0KIyB0d28gdmFyaWFibGVzLCBjb250aW51b3VzIHgsIGNvbnRpbnVvdXMgeSwgc2hvdyB0cmVuZCBhbmQgZGlzdHJpYnV0aW9uDQpuYW1lID0gYygncmFuaycsICdub19vZl9hc3NldHMnKQ0KZGYgPC0gcGxhc3RpYyAlPiUgcmVuYW1lKHggPSByYW5rLCB5ID0gbm9fb2ZfYXNzZXRzKSAlPiUgc2VsZWN0KHgsIHkpICU+JSBtdXRhdGUoeCA9IC14KSAjIHggPSAteCB0byBzaG93IHJhbmsgYXMgaW5jcmVhc2luZyBmcm9tIGxvdyB0byBoaWdoIA0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3Ntb290aC5odG1sDQpwb2ludF9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICAjIGdlb21faml0dGVyKGFscGhhID0gMC41LCBzaXplID0gMSkgKw0KICAgIGdlb21fcnVnKGFscGhhID0gMC41KSArICMgdHdvIDFkIG1hcmdpbmFsIGRpc3RyaWJ1dGlvbnMsIGRpc3BsYXkgaW5kaXZpZHVhbCBjYXNlcyBzbyBhcmUgYmVzdCB1c2VkIHdpdGggc21hbGxlciBkYXRhc2V0cw0KICAgIGdlb21fc21vb3RoKCkgKyAjIGFpZHMgdGhlIGV5ZSBpbiBzZWVpbmcgcGF0dGVybnMgaW4gdGhlIHByZXNlbmNlIG9mIG92ZXJwbG90dGluZw0KICAgIGdlb21fcG9pbnQoYWxwaGEgPSAwLjc1KSArICMgcG9pbnQgZ2VvbSBpcyB1c2VkIHRvIGNyZWF0ZSBzY2F0dGVycGxvdHMNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUocGFzdGUoInRyZW5kIG9mIiwgbmFtZVsyXSwgIm92ZXIiLCBuYW1lWzFdLCBzZXA9IiAiKSkgDQpwb2ludF9wbG90IDwtIGdncGxvdGx5KHBvaW50X3Bsb3QpICU+JSBsYXlvdXQoKQ0KDQp4X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnhfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHhfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQp5X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geSkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeV9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeV9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXVhbnRpbGUuaHRtbA0KcXVhbHRpbGVfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgZ2VvbV9xdWFudGlsZSgpICsgIyBmaXRzIGEgcXVhbnRpbGUgcmVncmVzc2lvbiB0byB0aGUgZGF0YSBhbmQgZHJhd3MgdGhlIGZpdHRlZCBxdWFudGlsZXMgd2l0aCBsaW5lcw0KICAgIHRoZW1lX21pbmltYWwoKQ0KcXVhbHRpbGVfcGxvdCA8LSBnZ3Bsb3RseShxdWFsdGlsZV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBtZXJnZSBmaWd1cmVzIGludG8gb25lIHBsb3QsIHZpYSBzdWJwbG90cywgaHR0cHM6Ly9wbG90bHktci5jb20vYXJyYW5naW5nLXZpZXdzLmh0bWwNCnN1YjEgPC0gc3VicGxvdCh4X2RlbnNpdHlfcGxvdCwgcGxvdGx5X2VtcHR5KCksIHBvaW50X3Bsb3QsIHlfZGVuc2l0eV9wbG90LCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuMTUsIDAuODUpLCB3aWR0aHMgPSBjKDAuODUsIDAuMTUpLCBzaGFyZVggPSBUUlVFLCBzaGFyZVkgPSBUUlVFLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0Kc3ViMiA8LSBzdWJwbG90KHF1YWx0aWxlX3Bsb3QsIHBsb3RseV9lbXB0eSgpLCBtYXJnaW4gPSAwLCB3aWR0aHMgPSBjKDAuODUsIDAuMTUpKSAlPiUgbGF5b3V0KCkNCmZpZyA8LSBzdWJwbG90KHN1YjEsIHN1YjIsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC44LCAwLjIpLCBzaGFyZVggPSBUUlVFKSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMV0pLCB5YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lWzJdKSkNCiAgDQpmaWcNCmBgYA0KYGBge3J9DQojIHR3byB2YXJpYWJsZXMsIGNvbnRpbnVvdXMgeCwgY29udGludW91cyB5LCBzaG93IHRyZW5kIGFuZCBkaXN0cmlidXRpb24NCm5hbWUgPSBjKCdyYW5rJywgJ3RvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uJykNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh4ID0gcmFuaywgeSA9IHRvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uKSAlPiUgc2VsZWN0KHgsIHkpICU+JSBtdXRhdGUoeCA9IC14KSAjIHggPSAteCB0byBzaG93IHJhbmsgYXMgaW5jcmVhc2luZyBmcm9tIGxvdyB0byBoaWdoIA0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3Ntb290aC5odG1sDQpwb2ludF9wbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICAjIGdlb21faml0dGVyKGFscGhhID0gMC41LCBzaXplID0gMSkgKw0KICAgIGdlb21fcnVnKGFscGhhID0gMC41KSArICMgdHdvIDFkIG1hcmdpbmFsIGRpc3RyaWJ1dGlvbnMsIGRpc3BsYXkgaW5kaXZpZHVhbCBjYXNlcyBzbyBhcmUgYmVzdCB1c2VkIHdpdGggc21hbGxlciBkYXRhc2V0cw0KICAgIGdlb21fc21vb3RoKCkgKyAjIGFpZHMgdGhlIGV5ZSBpbiBzZWVpbmcgcGF0dGVybnMgaW4gdGhlIHByZXNlbmNlIG9mIG92ZXJwbG90dGluZw0KICAgIGdlb21fcG9pbnQoYWxwaGEgPSAwLjc1KSArICMgcG9pbnQgZ2VvbSBpcyB1c2VkIHRvIGNyZWF0ZSBzY2F0dGVycGxvdHMNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUocGFzdGUoInRyZW5kIG9mIiwgbmFtZVsyXSwgIm92ZXIiLCBuYW1lWzFdLCBzZXA9IiAiKSkgDQpwb2ludF9wbG90IDwtIGdncGxvdGx5KHBvaW50X3Bsb3QpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UpKQ0KDQp4X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnhfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHhfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQp5X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geSkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeV9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeV9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXVhbnRpbGUuaHRtbA0KcXVhbHRpbGVfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgZ2VvbV9xdWFudGlsZShhbHBoYSA9IDAuOCkgKyAjIGZpdHMgYSBxdWFudGlsZSByZWdyZXNzaW9uIHRvIHRoZSBkYXRhIGFuZCBkcmF3cyB0aGUgZml0dGVkIHF1YW50aWxlcyB3aXRoIGxpbmVzDQogICAgdGhlbWVfbWluaW1hbCgpIA0KcXVhbHRpbGVfcGxvdCA8LSBnZ3Bsb3RseShxdWFsdGlsZV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9kZW5zaXR5XzJkLmh0bWwNCmRlbnNpdHlfMmRfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgZ2VvbV9kZW5zaXR5XzJkKGFscGhhID0gMC44LCBiaW5zID0gNCkgKyMgMkQga2VybmVsIGRlbnNpdHkgZXN0aW1hdGlvbiB1c2luZyBNQVNTOjprZGUyZCgpIGFuZCBkaXNwbGF5IHRoZSByZXN1bHRzIHdpdGggY29udG91cnMNCiAgICBnZW9tX3BvaW50KGFscGhhID0gMCkgKw0KICAgIHRoZW1lX21pbmltYWwoKQ0KZGVuc2l0eV8yZF9wbG90IDwtIGdncGxvdGx5KGRlbnNpdHlfMmRfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBtZXJnZSBmaWd1cmVzIGludG8gb25lIHBsb3QsIHZpYSBzdWJwbG90cywgaHR0cHM6Ly9wbG90bHktci5jb20vYXJyYW5naW5nLXZpZXdzLmh0bWwNCnN1YjEgPC0gc3VicGxvdCh4X2RlbnNpdHlfcGxvdCwgcGxvdGx5X2VtcHR5KCksIHBvaW50X3Bsb3QsIHlfZGVuc2l0eV9wbG90LCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuMTUsIDAuODUpLCB3aWR0aHMgPSBjKDAuODUsIDAuMTUpLCBzaGFyZVggPSBUUlVFLCBzaGFyZVkgPSBUUlVFKSAlPiUgbGF5b3V0KCkNCnN1YjIgPC0gc3VicGxvdChxdWFsdGlsZV9wbG90LCBkZW5zaXR5XzJkX3Bsb3QsIG1hcmdpbiA9IDAsIHdpZHRocyA9IGMoMC44NSwgMC4xNSkpICU+JSBsYXlvdXQoKQ0KZmlnIDwtIHN1YnBsb3Qoc3ViMSwgc3ViMiwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjgsIDAuMikpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsxXSksIHlheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMl0pKQ0KICANCmZpZw0KYGBg